package com.xbongbong.pro.statistic.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.xbongbong.paas.constant.BiConstant;
import com.xbongbong.paas.constant.DataConstant;
import com.xbongbong.paas.constant.FieldAttrConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.BIProductReformEnum;
import com.xbongbong.paas.enums.BelongEnum;
import com.xbongbong.paas.enums.BiEsAliasEnum;
import com.xbongbong.paas.enums.BiLinkEnum;
import com.xbongbong.paas.enums.BiRelTableEnum;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EsAliasEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.UnitEnum;
import com.xbongbong.paas.enums.VisibleTypeEnum;
import com.xbongbong.paas.enums.bi.ChartSourceEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.BiExplainPojo;
import com.xbongbong.paas.pojo.IdNamePojo;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.DepartmentVO;
import com.xbongbong.paas.toolbox.wrap.RoleSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.domain.entity.BiProWareEntity;
import com.xbongbong.pro.domain.entity.ChartDrillEntity;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.IntervalTypeEnum;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ChartProPermissionAliasEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.service.toolbox.statistic.help.ChartPermissionHelp;
import com.xbongbong.pro.statistic.ChartDrillItemPojo;
import com.xbongbong.pro.statistic.enums.ChartDrillWayEnum;
import com.xbongbong.pro.statistic.enums.ChartPermissionsTypeEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.enums.DrillDirEnum;
import com.xbongbong.pro.statistic.enums.NumFormatEnum;
import com.xbongbong.pro.statistic.enums.StatisticsTypeEnum;
import com.xbongbong.pro.statistic.model.ChartDrillModel;
import com.xbongbong.pro.statistic.pojo.AccumulatorPojo;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.pojo.ChartPermissionDetailsPojo;
import com.xbongbong.pro.statistic.pojo.ChartPermissionsPojo;
import com.xbongbong.pro.statistic.pojo.ChartTypeMemoPojo;
import com.xbongbong.pro.statistic.pojo.ExplainsPojo;
import com.xbongbong.pro.statistic.pojo.FileldPojo;
import com.xbongbong.pro.statistic.pojo.SlaveSourcePojo;
import com.xbongbong.pro.statistic.result.pojo.ChartDrillInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultChartFieldInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultChartInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.dto.ChartResultDTO;
import com.xbongbong.pro.statistic.service.BiProWareService;
import com.xbongbong.pro.statistic.service.ChartLimitService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.CustomChartConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ProductCategoryEntity;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.UserTeamEnum;
import com.xbongbong.saas.enums.WorkOrderTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.WorkOrderV2NodeLogInfoEnum;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.ProductCategoryModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.paas.enums.IndexTypeEnum.IDX_SAAS_CUSTOMER_COMMUNICATE;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author 梁鲁江
 * @version v1.0
 * @date 2019/3/29 9:33
 * @since v1.0
 */
@Component
public class CustomHelp {
    private static final Logger LOG = LoggerFactory.getLogger(CustomHelp.class);

    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ChartPermissionHelp chartPermissionHelp;
    @Resource
    private BiProWareService biProWareService;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private ChartDrillModel chartDrillModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private ProductCategoryModel productCategoryModel;
    @Resource
    private ChartLimitService chartLimitService;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private DrillHelp drillHelp;

    /**
     * 获取索引
     * @param hasSecondSlave
     * @param slaveSourceList
     * @param businessType
     * @param saasMark
     * @return
     * @throws XbbException
     */
    public BiRelTableEnum getBiRelTableEnum(boolean hasSecondSlave, List<SlaveSourcePojo> slaveSourceList, Integer businessType, Integer saasMark) throws XbbException {
        BiRelTableEnum biRelTableEnum;
        if (SaasMarkEnum.SAAS.getCode().equals(saasMark)) {
            if (SaasMarkEnum.SAAS.getCode().equals(slaveSourceList.get(0).getSaasMark())) {
                //处理前两张为SAAS
                String mutiCode = "";
                if (hasSecondSlave) {
                    if (SaasMarkEnum.SAAS.getCode().equals(slaveSourceList.get(1).getSaasMark())) {
                        //三张表都是SAAS
                        mutiCode = businessType + "_" + slaveSourceList.get(0).getBusinessType() + "_" + slaveSourceList.get(1).getBusinessType();
                        biRelTableEnum = BiRelTableEnum.getByMutiCode(mutiCode);
                        //因为后两张顺序不限制
                        if(biRelTableEnum == null){
                            mutiCode = businessType  + "_" + slaveSourceList.get(1).getBusinessType() + "_" + slaveSourceList.get(0).getBusinessType();
                            biRelTableEnum = BiRelTableEnum.getByMutiCode(mutiCode);
                        }

                    } else {
                        //第三张表是自定义
                        mutiCode = businessType + "_" + slaveSourceList.get(0).getBusinessType();
                        biRelTableEnum = BiRelTableEnum.getByMutiCode(mutiCode);
                    }
                }else {
                    //只有两张，且都为系统
                    mutiCode = businessType + "_" + slaveSourceList.get(0).getBusinessType();
                    biRelTableEnum = BiRelTableEnum.getByMutiCode(mutiCode);
                    if(biRelTableEnum == null){
                        biRelTableEnum = BiRelTableEnum.getByRefCode(businessType);
                    }
                }
            }else if(hasSecondSlave && SaasMarkEnum.SAAS.getCode().equals(slaveSourceList.get(1).getSaasMark())){
                //处理第二张为自定义,但是第三张为SAAS
                biRelTableEnum = BiRelTableEnum.getByMutiCode(businessType + "_" + slaveSourceList.get(1).getBusinessType());
            } else {
                //后二张表是自定义（归为自定义）
//                biRelTableEnum = BiRelTableEnum.getByRefCode(businessType);
                biRelTableEnum = BiRelTableEnum.IDX_STATISTIC_PASS_DATA;
            }
            if(biRelTableEnum == null && slaveSourceList.get(0).getDriveLinkedAttr() != null){
                //自定义字段 关联数据类型情况下
                biRelTableEnum = BiRelTableEnum.IDX_STATISTIC_DEFAULT_DATA;
            }
        } else {
            //第一张表就是自定义表单，则归为自定义
            biRelTableEnum = BiRelTableEnum.IDX_STATISTIC_PASS_DATA;
        }
        //索引有误，无法进行初始化，直接报错
        if(biRelTableEnum == null){
            throw  new XbbException(BiErrorCodeEnum.API_ERROR_241009);
        }
        return biRelTableEnum;
    }

    public BiRelTableEnum getBiRelTableEnum(Integer businessType, Integer saasMark) {
        BiRelTableEnum biRelTableEnum = null;
        //获取枚举
        if(SaasMarkEnum.SAAS.getCode().equals(saasMark)){
            biRelTableEnum = BiRelTableEnum.getByRefCode(businessType);
        }else if(SaasMarkEnum.PAAS.getCode().equals(saasMark)){
            biRelTableEnum = BiRelTableEnum.IDX_STATISTIC_PASS_DATA;
        }
        if(biRelTableEnum == null){
            biRelTableEnum = BiRelTableEnum.IDX_STATISTIC_PASS_DATA;
        }
        return biRelTableEnum;
    }

    /**
     * 追加关联字段到判断中
     * @param stringBuilder 载体
     * @param linkAttr  关联字段
     */
    public void stringAppend(StringBuilder stringBuilder, String linkAttr) {
        if(StringUtil.isNotEmpty(linkAttr)){
            stringBuilder.append("_"+linkAttr.trim());
        }
    }

    /**
     * 获取默认关联字段
     * @param businessType
     * @param saasMark
     * @param slaveBusinessType
     * @param slaveSaasMark
     * @return
     * @throws XbbException
     */
    public BiLinkEnum getBiLinkEnum( Integer businessType, Integer saasMark,Integer slaveBusinessType, Integer slaveSaasMark) throws XbbException {
        BiLinkEnum biLinkEnum;
        if (SaasMarkEnum.SAAS.getCode().equals(saasMark) && SaasMarkEnum.SAAS.getCode().equals(slaveSaasMark) ) {
            String mutiCode = businessType + "_" +slaveBusinessType;
            biLinkEnum = BiLinkEnum.getByMutiCode(mutiCode);
            if(biLinkEnum == null){
                mutiCode = slaveBusinessType + "_" + businessType;
                biLinkEnum = BiLinkEnum.getByMutiCode(mutiCode);
            }
            return biLinkEnum;
        }
        return null;
    }


    /**
     * 设置自定义指标的单位
     * @param chartEntity  图表实体
     * @return 返回单位
     */
    public String setUnit(ChartEntity chartEntity) {
        String unit = chartEntity.getUnit();
        if(Objects.equals(UnitEnum.CUSTOM.getAlias(),unit)){
            JSONObject explainJson = chartEntity.getExplains();
            if(explainJson != null && !explainJson.isEmpty()){
                ExplainsPojo explainsPojo = explainJson.toJavaObject(ExplainsPojo.class);
                unit = explainsPojo.getUnitValue();
            }
        }else {
            UnitEnum unitEnum = UnitEnum.getByAlias(unit);
            if(unitEnum != null){
                unit = unitEnum.getName();
            }
        }
        return unit;
    }

    /**
     * 判断是否在data中
     * @param fieldType
     * @return
     */
    public int setInData(Integer fieldType) {
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
        int inData = 0;
        if(fieldTypeEnum != null){
            if(BelongEnum.SYSTEM.getAlias().equals(fieldTypeEnum.getBelong())){
                inData = DataConstant.NOT_IN_DATA;
            }else {
                inData = DataConstant.IN_DATA;
            }
        }else {
            //TODO  异常抛出
        }
        return inData;
    }

    /**
     * 获取字段，以判断是否加data.
     * @param fieldAttrEntity
     * @return
     */
    public String getAttr(FieldAttrEntity fieldAttrEntity) {
        String attr;
        int inData = setInData(fieldAttrEntity.getFieldType());
        attr = fieldAttrEntity.getAttr();
        if (Objects.equals(DataConstant.IN_DATA, inData)) {
            attr = DataConstant.PREFIX_DATA + attr;
        }
        return attr;
    }

    /**
     * 获取字段，以判断是否加data.和.keyword
     * @param fieldAttrEntity
     * @return
     */
    public String getAttr4Keyword(FieldAttrEntity fieldAttrEntity) {
        String attr = getAttr(fieldAttrEntity);
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldAttrEntity.getFieldType());
        //字段类型为text，或者字段在es内的类型时text，则需要在后面拼上“.keyword”
        boolean flag = fieldTypeEnum == FieldTypeEnum.TEXT || (fieldTypeEnum != null && "text".equals(fieldTypeEnum.getEsalias()));
        if (flag) {
            return attr + StringConstant.POINT + StringConstant.KEY_WORD;
        }
        return attr;
    }

    /**
     * 设置 字段是否在data中
     * @param slaveSourcePojo  选定的数据源
     */
    public void setInData(SlaveSourcePojo slaveSourcePojo) {
        int inData = setInData(slaveSourcePojo.getFieldType());
        slaveSourcePojo.setInData(inData);
    }

    /**
     * 设置除了第一个关联字段之外的其他关联字段
     * @param slaveSourcePojo
     */
    public void setSecondInData(SlaveSourcePojo slaveSourcePojo) {
        Integer secondFieldType = slaveSourcePojo.getSecondFieldType();
        if(secondFieldType !=null){
            int inData = setInData(secondFieldType);
            slaveSourcePojo.setSecondInData(inData);
        }
        if( slaveSourcePojo.getLinkAttrCFieldType() != null){
            int inData = setInData(slaveSourcePojo.getLinkAttrCFieldType());
            slaveSourcePojo.setLinkAttrCInData(inData);
        }
        if( slaveSourcePojo.getLinkAttrDFieldType() != null){
            int inData = setInData(slaveSourcePojo.getLinkAttrDFieldType());
            slaveSourcePojo.setLinkAttrDInData(inData);
        }
        if( slaveSourcePojo.getLinkAttrEFieldType() != null){
            int inData = setInData(slaveSourcePojo.getLinkAttrEFieldType());
            slaveSourcePojo.setLinkAttrEInData(inData);
        }
    }

    public void setSecondInData(SlaveSourcePojo driver,List<SlaveSourcePojo> slaveSourceList) {
        if(CollectionsUtil.isNotEmpty(slaveSourceList)){
            //从1开始，因为0的已经用通用方法设置过
            for (int i = 1; i < slaveSourceList.size(); i++) {
                Integer  fieldType  = slaveSourceList.get(i).getSecondFieldType();
                int  inData = setInData(fieldType);
                if(Objects.equals(i,1)){
                    driver.setSecondInData(inData);
                    driver.setSecondFieldType(fieldType);
                }else if(Objects.equals(i,2)){
                    driver.setLinkAttrCInData(inData);
                    driver.setLinkAttrCFieldType(fieldType);
                } else if(Objects.equals(i,3)){
                    driver.setLinkAttrDInData(inData);
                    driver.setLinkAttrDFieldType(fieldType);
                } else if(Objects.equals(i,4)){
                    driver.setLinkAttrEInData(inData);
                    driver.setLinkAttrEFieldType(fieldType);
                }
            }
        }
    }

    /**
     * 设置关联字段
     * @param chartEntity
     * @throws XbbException
     */
    public void setSourcePojo(ChartEntity chartEntity) throws XbbException {
        setSourcePojo(chartEntity,true);
    }

    public void setSourcePojo(ChartEntity chartEntity,boolean updateFormIdAttr) throws XbbException {
        //多表的关联
        if (Objects.equals(chartEntity.getMuti(),0) && !Objects.equals(ChartSourceEnum.DATESET.getCode(),chartEntity.getSingle())) {
            JSONObject driverSource = chartEntity.getDriverSources();
            SlaveSourcePojo driverSourcePojo = JSON.toJavaObject(driverSource, SlaveSourcePojo.class);
            JSONArray slaveSources = chartEntity.getSlaveSources();
            List<SlaveSourcePojo> slaveSourceList = slaveSources.toJavaList(SlaveSourcePojo.class);
            setSourcePojo(chartEntity, driverSourcePojo, slaveSourceList);
            setOriginalAttr(chartEntity, updateFormIdAttr);
        }
    }

    public void setSourcePojo(ChartEntity chartEntity, SlaveSourcePojo driverSourcePojo, List<SlaveSourcePojo> slaveSourceList) throws XbbException {
        boolean linkAttFlag = Objects.equals("-1", driverSourcePojo.getLinkAttr());
        boolean secondLinkAttFlag = Objects.equals("-1", driverSourcePojo.getLinkAttrB());
        if(linkAttFlag){
            setDefaultAttr(driverSourcePojo, slaveSourceList, 0);
        }
        if(secondLinkAttFlag){
            setDefaultAttr(driverSourcePojo, slaveSourceList, 1);
        }
        if(Objects.equals("-1", driverSourcePojo.getLinkAttrC())){
            setDefaultAttr(driverSourcePojo, slaveSourceList, 2);
        }
        if(Objects.equals("-1", driverSourcePojo.getLinkAttrD())){
            setDefaultAttr(driverSourcePojo, slaveSourceList, 3);
        }
        if(Objects.equals("-1", driverSourcePojo.getLinkAttrE())){
            setDefaultAttr(driverSourcePojo, slaveSourceList, 4);
        }
        setInData(driverSourcePojo);
        //老数据有secondFieldType，新数据没有，要从从表里获取
        if(driverSourcePojo.getSecondFieldType() !=null){
            setSecondInData(driverSourcePojo);
        }else {
            setSecondInData(driverSourcePojo,slaveSourceList);
        }
        for (SlaveSourcePojo slaveSourcePojo : slaveSourceList) {
            setInData(slaveSourcePojo);
        }
        //把相关信息更新回去
        chartEntity.setDriverSources(JSON.parseObject(JSON.toJSON(driverSourcePojo).toString()));
        chartEntity.setSlaveSources(JSON.parseArray(JSON.toJSON(slaveSourceList).toString()));
    }

    /**
     * 设置源字段和仓库新字段之间的关系
     * 例如 客户里的text_1存储到数据仓库里的text_20中
     * @param chartEntity
     */
    public void setOriginalAttr(ChartEntity chartEntity,boolean updateFormIdAttr) throws XbbException {
        JSONArray displayArray = chartEntity.getDisplayAttr();
        JSONArray rowGroupAttr = chartEntity.getRowGroupAttr();
        JSONArray colGroupAttr = chartEntity.getColGroupAttr();
        JSONArray summaryArray = chartEntity.getSummaryAttr();
        JSONArray computedNumAttr = chartEntity.getComputedNumAttr();
        JSONArray chartClassifyArray = chartEntity.getChartClassify();
        JSONArray chartSeriesArray = chartEntity.getChartSeries();
        JSONArray chartValueArray = chartEntity.getChartValue();
        JSONArray chartValueSecondArray = chartEntity.getChartValueSecond();
        JSONArray secondTargetAttr = chartEntity.getSecondTargetAttr();
        JSONArray penetrateArray = chartEntity.getPenetrateAttr();
        JSONArray searchArray = chartEntity.getSearch();
        JSONArray filterArray = chartEntity.getFilter();
        JSONArray drill = chartEntity.getDrill();
        //做两个集合
        //1.key 为 源Attr   把原来的字段新attr赋值上去
        // 2.formId 对应的原始originalAttr->attr
        //时间类的放在date字段上
        //保证此处只被调用一次
        AccumulatorPojo accumulatorPojo = new AccumulatorPojo();
        //key : originalAttr +"_"+ formId
        Map<String,Object>  selectedMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //formId:<originalAttr :attr>
        Map<String,Map<String,String>>  selectedByFormIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //不更新，只是用来判断
        if(!updateFormIdAttr){
            JSONObject selectedAttr = chartEntity.getSelectedAttr();
            if(selectedAttr != null){
                for (Map.Entry<String, Object> stringObjectEntry : selectedAttr.entrySet()) {
                    selectedMap.put(stringObjectEntry.getKey(), stringObjectEntry.getValue());
                }
            }
        }
        setSelectedAttr(displayArray, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(displayArray)){
            chartEntity.setDisplayAttr(displayArray);
        }
        setSelectedAttr(rowGroupAttr, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(rowGroupAttr)){
            chartEntity.setRowGroupAttr(rowGroupAttr);
        }
        setSelectedAttr(colGroupAttr, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(colGroupAttr)){
            chartEntity.setColGroupAttr(colGroupAttr);
        }
        setSelectedAttr(summaryArray, selectedMap,selectedByFormIdMap, accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(summaryArray)){
            chartEntity.setSummaryAttr(summaryArray);
        }
        setSelectedAttr(chartClassifyArray, selectedMap,selectedByFormIdMap, accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(chartClassifyArray)){
            chartEntity.setChartClassify(chartClassifyArray);
        }
        setSelectedAttr(chartSeriesArray, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(chartSeriesArray)){
            chartEntity.setChartSeries(chartSeriesArray);
        }
        setSelectedAttr(chartValueArray, selectedMap,selectedByFormIdMap, accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(chartValueArray)){
            chartEntity.setChartValue(chartValueArray);
        }
        setSelectedAttr(penetrateArray, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(penetrateArray)){
            chartEntity.setPenetrateAttr(penetrateArray);
        }
        setSelectedAttr(computedNumAttr, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(computedNumAttr)){
            chartEntity.setComputedNumAttr(computedNumAttr);
        }
        setSelectedAttr(chartValueSecondArray, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(chartValueSecondArray)){
            chartEntity.setComputedNumAttr(chartValueSecondArray);
        }
        setSelectedAttr(secondTargetAttr, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(secondTargetAttr)){
            chartEntity.setComputedNumAttr(secondTargetAttr);
        }
        setSearchAttr(searchArray, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(searchArray)){
            chartEntity.setSearch(searchArray);
        }
        setSearchAttr(filterArray, selectedMap, selectedByFormIdMap,accumulatorPojo);
        if(CollectionsUtil.isNotEmpty(filterArray)){
            chartEntity.setFilter(filterArray);
        }
        setDrillAttr(drill, selectedMap, selectedByFormIdMap, accumulatorPojo);
        if (CollectionUtils.isNotEmpty(drill)) {
            chartEntity.setDrill(drill);
        }
        //数据权限字段映射
        JSONObject permission = chartEntity.getPermissions();
        JSONObject dataPermissionAttr = permission == null ? null : permission.getJSONObject("dataPermissionAttr");
        if (dataPermissionAttr != null && !dataPermissionAttr.isEmpty()) {
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(dataPermissionAttr);
            setSelectedAttr(jsonArray, selectedMap, selectedByFormIdMap, accumulatorPojo);
            permission.put("dataPermissionAttr", jsonArray.getJSONObject(0));
            chartEntity.setPermissions(permission);
        }
        if(updateFormIdAttr){
            JSONObject driverSources = chartEntity.getDriverSources();
            SlaveSourcePojo driverSourcePojo = driverSources.toJavaObject(SlaveSourcePojo.class);
            JSONArray slaveSources = chartEntity.getSlaveSources();
            //团队的特殊处理  单表+有团队+统计表、图  这里不用再判断具体的字段，外面做过处理
            if(ChartTypeEnum.getGroupChartType().contains(chartEntity.getChartType()) && UserTeamEnum.hasTeam(driverSourcePojo.getBusinessType()) && CollectionsUtil.isEmpty(slaveSources)){
                PaasFormExplainEntity  formExplain = paasFormExplainModel.getByFormId(driverSourcePojo.getFormId(),chartEntity.getCorpid());
                List<FieldAttrEntity> explainList = JSON.parseArray(formExplain.getExplains(), FieldAttrEntity.class);
                explainList.forEach(explain ->{
                    explain.setFormId(driverSourcePojo.getFormId());
                });
                setSelectedAttr(JSON.parseArray(JSON.toJSONString(explainList)), selectedMap, selectedByFormIdMap,accumulatorPojo);
            }
            //必要信息的处理
            JSONArray  baseJsonArray = new JSONArray();
            setNecessaryAttr(baseJsonArray, driverSourcePojo.getFormId());
            setNecessaryAttrByBusiness(baseJsonArray, driverSourcePojo);
            for (int i = 0; i < slaveSources.size(); i++) {
                JSONObject slaveSourcesJSONObject = slaveSources.getJSONObject(i);
                setNecessaryAttr(baseJsonArray, slaveSourcesJSONObject.getLong(BiEsAliasEnum.FORMID.getEsAlias()));
                setNecessaryAttrByBusiness(baseJsonArray, slaveSourcesJSONObject.toJavaObject(SlaveSourcePojo.class));
            }
            setSelectedAttr(baseJsonArray, selectedMap, selectedByFormIdMap,accumulatorPojo);
            chartEntity.setFormIdAttr((JSONObject) JSON.toJSON(selectedByFormIdMap));
            chartEntity.setSelectedAttr((JSONObject) JSON.toJSON(selectedMap));
        }
    }

    /**
     * 根据业务类型设置必要的字段
     * @param baseJsonArray
     * @param driverSourcePojo
     */
    private void setNecessaryAttrByBusiness(JSONArray baseJsonArray, SlaveSourcePojo driverSourcePojo) {
        if(Objects.equals(driverSourcePojo.getSaasMark(), SaasMarkEnum.SAAS.getCode())){
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(driverSourcePojo.getBusinessType());
            switch (xbbRefTypeEnum){
                case CONTRACT:
                    baseJsonArray.add(new BiExplainPojo(ContractEnum.IS_RED.getAttr(),"", FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), driverSourcePojo.getFormId(),""));
                    break;
                case CUSTOMER_COMMUNICATE:
                    //过滤项目日志
                    baseJsonArray.add(new BiExplainPojo(CustomerCommunicateEnum.AUTO_GEN.getAttr(),"", FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), driverSourcePojo.getFormId(),""));
                    break;
                case PAYMENT_SHEET:
                case WRITE_OFF_PREPAYMENT:
                case RED_PAYMENT_SHEET:
                case RED_PREPAYMENT:
                case RED_WRITE_OFF_PREPAYMENT:
                case RED_WRITE_OFF_BALANCE:
                case PREPAYMENT:
                case BAD_DEBT:
                case PAY_SHEET:
                case WRITE_OFF_PREPAY:
                case RED_WRITE_OFF_PAY:
                case RED_PREPAY:
                case RED_WRITE_OFF_PREPAY:
                case PREPAY:
                case BAD_PAY:
                    baseJsonArray.add(new BiExplainPojo(FieldTypeEnum.SHEET_ALONE.getAlias(),"", FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), driverSourcePojo.getFormId(),""));
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 设置必要字段（基本信息如formId、创建人、创建时间、更新时间）
     * @param baseJsonArray
     * @param formId
     */
    private void setNecessaryAttr(JSONArray baseJsonArray, Long formId) {
        baseJsonArray.add(new BiExplainPojo(BiEsAliasEnum.ID.getEsAlias(),"", FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo(BiEsAliasEnum.DATAID.getEsAlias(),"", FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo(BiEsAliasEnum.FORMID.getEsAlias(),"",FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo(BiEsAliasEnum.OWNERID.getEsAlias(),"",FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo(BiEsAliasEnum.DEPARTMENTID.getEsAlias(),"",FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo(BiEsAliasEnum.FLOWSTATUS.getEsAlias(),"",FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo(BiEsAliasEnum.CREATORID.getEsAlias(),"",FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo("updateTime","",FieldTypeEnum.DATETIME.getEsalias(),FieldTypeEnum.DATETIME.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo("addTime","",FieldTypeEnum.DATETIME.getEsalias(),FieldTypeEnum.DATETIME.getType(), formId,""));
        baseJsonArray.add(new BiExplainPojo("del","",FieldTypeEnum.NUM.getEsalias(),FieldTypeEnum.NUM.getType(), formId,""));
    }

    /**
     * 处理查询筛选条件的字段映射
     * @param jsonArray 字段内容
     * @param selectedMap 关系映射
     * @author zhouwq
     * @date 2020/7/22 11:26
     */
    private void setSearchAttr(JSONArray jsonArray, Map<String,Object>  selectedMap, Map<String,Map<String,String>>  selectedByFormIdMap ,AccumulatorPojo accumulatorPojo) {
        if (CollectionsUtil.isNotEmpty(jsonArray)) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                BiExplainPojo biExplainPojo = jsonObject.toJavaObject(BiExplainPojo.class);
                Long formId = biExplainPojo.getFormId();
                Map<String, String> attrKeyMap = null;
                try {
                    attrKeyMap = selectedByFormIdMap.get(formId.toString());
                } catch (Exception e) {
                    LOG.error("======="+selectedByFormIdMap+"======"+formId+"====="+jsonObject+"====="+biExplainPojo,e);
                }
                String originalAttr = biExplainPojo.getOriginalAttr();
                String parentAttr = biExplainPojo.getParentAttr();
                boolean isSubFormType = StringUtil.isNotEmpty(parentAttr);
                //original如果存在（不包括“”）则证明已经处理过属于编辑  parent
                originalAttr = StringUtil.isNotEmpty(originalAttr) ? originalAttr : biExplainPojo.getAttr();
                //使用中划线，后面易于和原有字段内的下划线
                String key = parentAttr ==  null || Objects.equals(parentAttr, "") ? originalAttr + "-" + biExplainPojo.getFormId() : parentAttr + "-" + biExplainPojo.getFormId();
                String attr = "";
                //防重复
                if (selectedMap.get(key) != null) {
                    Object value = selectedMap.get(key);
                    JSONObject jsonValue = JSON.parseObject(value.toString());
                    BiExplainPojo biExplainPojoValue = jsonValue.toJavaObject(BiExplainPojo.class);
                    attr = biExplainPojoValue.getAttr();
                    if (isSubFormType) {
                        if (attr.contains(".")) {
                            attr = attr.split("\\.")[0];
                        }
                        try {
                            attr = attr + StringConstant.POINT + biExplainPojo.getAttr().split("\\.")[1];
                        } catch (ArrayIndexOutOfBoundsException e) {
                            continue;
                        }
                    }
                } else {
                    biExplainPojo.setOriginalAttr(originalAttr);
                    //此处直接使用attr判断，使用fieldType要再找一次不如直接判断简单
                    if (originalAttr.contains(EsAliasEnum.SUB_FORM.getEsAlias())) {
                        String subAttr = EsAliasEnum.SUB_FORM.getEsAlias() + "_" + accumulatorPojo.getSubFormAccum();
                        if (isSubFormType) {
                            try {
                                attr = subAttr + StringConstant.POINT + biExplainPojo.getAttr().split("\\.")[1];
                            } catch (ArrayIndexOutOfBoundsException e) {
                                continue;
                            }
                        }
                    } else if (originalAttr.contains(EsAliasEnum.NUM.getEsAlias())) {attr = EsAliasEnum.NUM.getEsAlias() + "_" + accumulatorPojo.getNumAccum();
                    } else if (originalAttr.contains(EsAliasEnum.ADDRESS.getEsAlias()) || originalAttr.contains(EsAliasEnum.GEO.getEsAlias())) {
                        attr = handleAddressAttr(originalAttr, attrKeyMap, accumulatorPojo);
                    } else if (originalAttr.contains(EsAliasEnum.DATE.getEsAlias())) {
                        attr = EsAliasEnum.DATE.getEsAlias() + "_" + accumulatorPojo.getDateAccum();
                    } else if (originalAttr.contains(EsAliasEnum.TEXT.getEsAlias())) {
                        //TODO 这里要去判断MAX值
                        attr = EsAliasEnum.TEXT.getEsAlias() + "_" + accumulatorPojo.getTextAccum();
                    }  else if (originalAttr.contains(EsAliasEnum.FILE.getEsAlias())) {
                        attr = EsAliasEnum.FILE.getEsAlias() + "_" + accumulatorPojo.getFileAccum();
                    } else if (originalAttr.contains(EsAliasEnum.ARRAY.getEsAlias())) {
                        attr = EsAliasEnum.ARRAY.getEsAlias() + "_" + accumulatorPojo.getArrayAccum();
                    } else if (originalAttr.contains("Time")) {
                        //时间类的处理，归集到date里,例如
                        attr = EsAliasEnum.DATE.getEsAlias() + "_" + accumulatorPojo.getDateAccum();
                    } else if (originalAttr.contains(BiEsAliasEnum.FORMID.getEsAlias())) {
                        attr = BiEsAliasEnum.FORMID.getEsAlias() + "_" + accumulatorPojo.getFormIdAccum();
                    } else if (originalAttr.contains(BiEsAliasEnum.SERIALNO.getEsAlias())) {
                        //流水号放到text里面
                        attr = BiEsAliasEnum.TEXT.getEsAlias() + "_" + accumulatorPojo.getTextAccum();
                    } else if (originalAttr.contains(BiEsAliasEnum.OWNERID.getEsAlias())) {
                        attr = BiEsAliasEnum.OWNERID.getEsAlias() + "_" + accumulatorPojo.getOwnerIdAccum();
                    }else if (originalAttr.contains(FieldTypeEnum.COUSERID.getAlias())) {
                        attr = FieldTypeEnum.COUSERID.getAlias() + "_" + accumulatorPojo.getCoUserIdAccum();
                    } else if (originalAttr.contains(BiEsAliasEnum.DEPARTMENTID.getEsAlias())) {
                        attr = BiEsAliasEnum.DEPARTMENTID.getEsAlias() + "_" + accumulatorPojo.getDepartmentIdAccum();
                    } else if (originalAttr.contains(BiEsAliasEnum.FLOWSTATUS.getEsAlias())) {
                        attr = BiEsAliasEnum.FLOWSTATUS.getEsAlias() + "_" + accumulatorPojo.getFlowStatusAccum();
                    } else if (originalAttr.contains(BiEsAliasEnum.CREATORID.getEsAlias())) {
                        attr = BiEsAliasEnum.CREATORID.getEsAlias() + "_" + accumulatorPojo.getCreatorIdAccum();
                    } else if (originalAttr.contains(BiEsAliasEnum.DATAID.getEsAlias())) {
                        attr = BiEsAliasEnum.DATAID.getEsAlias() + "_" + accumulatorPojo.getDataIdAccum();
                    } else if(originalAttr.contains("del")){
                        attr = EsAliasEnum.NUM.getEsAlias() + "_" + accumulatorPojo.getNumAccum();
                    } else if(originalAttr.contains(FieldTypeEnum.SHEET_ALONE.getAlias())){
                        attr = EsAliasEnum.NUM.getEsAlias() + "_" + accumulatorPojo.getNumAccum();
                    } else {
                        //TODO
                        //例如corpid不需要归集的字段
                        attr = originalAttr;
                    }
                    biExplainPojo.setAttr(attr);
                    selectedMap.put(key, JSON.toJSON(biExplainPojo));
                    if (attrKeyMap != null) {
                        if (!attrKeyMap.containsKey(originalAttr)) {
                            attrKeyMap.put(originalAttr, attr);
                        }
                    } else {
                        attrKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        attrKeyMap.put(originalAttr, attr);
                    }
                    selectedByFormIdMap.put(formId.toString(), attrKeyMap);
                }
                jsonObject.put("attr", attr);
                jsonObject.put("originalAttr", originalAttr);
                jsonArray.set(i, jsonObject);
            }
        }
    }

    /**
     *
     * @param jsonArray  待处理的字段
     * @param selectedMap   选中的字段
     * @param selectedByFormIdMap   选中的字段按照formId归集
     * @param accumulatorPojo 累加器
     * @return
     */
    private JSONArray setSelectedAttr(JSONArray jsonArray, Map<String,Object>  selectedMap, Map<String,Map<String,String>>  selectedByFormIdMap ,AccumulatorPojo accumulatorPojo) {
        if(CollectionsUtil.isNotEmpty(jsonArray)){
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                handleAttrMapping(jsonObject, selectedMap, selectedByFormIdMap, accumulatorPojo);
                jsonArray.set(i,jsonObject);
                JSONObject subForm = jsonObject.getJSONObject("subForm");
                if (subForm != null && subForm.get("items") != null) {
                    List<ChartFieldAttrPojo> itemArr = JSON.parseArray(JSON.toJSONString(subForm.get("items")), ChartFieldAttrPojo.class);
                    subForm.put("items", itemArr);
                }
                ChartFieldAttrPojo chartFieldAttrPojo = JSON.parseObject(jsonObject.toJSONString(), ChartFieldAttrPojo.class);
                Integer fieldType = chartFieldAttrPojo.getFieldType();
                if (FieldTypeEnum.LINK_BUSINESS_SINGLE.getType().equals(fieldType) || FieldTypeEnum.LINK_BUSINESS_MULTI.getType().equals(fieldType) || FieldTypeEnum.BIRTHDAY.getType().equals(fieldType)) {
                    if (chartFieldAttrPojo.getLinkedAttr() != null) {
                        JSONObject linkedJsonObject = chartFieldAttrPojo.getLinkedAttr();
                        String attr = handleAttrMapping(linkedJsonObject, selectedMap, selectedByFormIdMap, accumulatorPojo);
                        jsonObject.put("linkedText", attr);
                    }
                }
            }
        }
        return jsonArray;
    }

    /**
     * 处理钻取信息内的字段映射
     * @param drill 钻取信息
     * @param selectedMap key : originalAttr +"_"+ formId
     * @param selectedByFormIdMap formId:<originalAttr :attr>
     * @param accumulatorPojo 累加器，记录每种类型字段的位置
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void setDrillAttr(JSONArray drill, Map<String,Object>  selectedMap, Map<String,Map<String,String>>  selectedByFormIdMap ,AccumulatorPojo accumulatorPojo) {
        if (CollectionsUtil.isEmpty(drill)) {
            return;
        }
        for (int i = 0; i < drill.size(); i++) {
            JSONObject jsonObject = drill.getJSONObject(i);
            JSONArray field = jsonObject.getJSONArray(BusinessConstant.FIELD);
            if (CollectionUtils.isEmpty(field)) {
                continue;
            }
            setSelectedAttr(field, selectedMap, selectedByFormIdMap, accumulatorPojo);
            drill.set(i, jsonObject);
        }
    }

    private void collectSelectArray(JSONArray wildArray, JSONArray selectArray) {
        if(CollectionsUtil.isNotEmpty(wildArray)){
            selectArray.addAll(wildArray);
        }
    }


    /**
     * 设置默认的关联字段
     * @param driverSourcePojo
     * @param slaveSourceList
     * @param i
     * @throws XbbException
     */
    private void setDefaultAttr(SlaveSourcePojo driverSourcePojo, List<SlaveSourcePojo> slaveSourceList, int i) throws XbbException {
        try {
            BiLinkEnum biLinkEnum  =  getBiLinkEnum(driverSourcePojo.getBusinessType(), driverSourcePojo.getSaasMark(),slaveSourceList.get(i).getBusinessType(),slaveSourceList.get(i).getSaasMark());
            if(biLinkEnum == null){
                throw  new XbbException(BiErrorCodeEnum.API_ERROR_241009);
            }
            JSONObject defaultAttr = JsonHelperUtil.parseObject(biLinkEnum.getDefaultAttr());
            JSONObject fieldJson = defaultAttr.getJSONObject(driverSourcePojo.getBusinessType().toString());
            FileldPojo fileldPojo = fieldJson.toJavaObject(FileldPojo.class);
            //设置主表
            String attr = fileldPojo.getAttr();
            Integer fieldType = fileldPojo.getFieldType();
            int inData = setInData(fieldType);
            if(Objects.equals(0,i)){
                driverSourcePojo.setLinkAttrCopy(attr);
                driverSourcePojo.setFieldType(fieldType);
                driverSourcePojo.setInData(inData);
            }else if(Objects.equals(1,i)){
                driverSourcePojo.setLinkAttrBCopy(attr);
                driverSourcePojo.setSecondFieldType(fieldType);
                driverSourcePojo.setSecondInData(inData);
            }else if(Objects.equals(2,i)){
                driverSourcePojo.setLinkAttrCCopy(attr);
                driverSourcePojo.setLinkAttrCFieldType(fieldType);
                driverSourcePojo.setLinkAttrCInData(inData);
            }else if(Objects.equals(3,i)){
                driverSourcePojo.setLinkAttrDCopy(attr);
                driverSourcePojo.setLinkAttrDFieldType(fieldType);
                driverSourcePojo.setLinkAttrDInData(inData);
            }else if(Objects.equals(4,i)){
                driverSourcePojo.setLinkAttrECopy(attr);
                driverSourcePojo.setLinkAttrEFieldType(fieldType);
                driverSourcePojo.setLinkAttrEInData(inData);
            }
            //设置从表
            setDefaultAttr(slaveSourceList, defaultAttr,i);
        } catch (XbbException e) {
            LOG.error(BiErrorCodeEnum.API_ERROR_241012.getMsg(),e);
            throw  new XbbException(BiErrorCodeEnum.API_ERROR_241012);
        }
    }
    /**
     * 设置默认关联字段
     * @param slaveSourceList
     * @param defaultAttr
     * @param i
     * @throws XbbException
     */
    private void setDefaultAttr(List<SlaveSourcePojo> slaveSourceList, JSONObject defaultAttr,int i) throws XbbException {
        JSONObject secondFieldJson = defaultAttr.getJSONObject(slaveSourceList.get(i).getBusinessType().toString());
        if(secondFieldJson.isEmpty()){
            throw  new XbbException(BiErrorCodeEnum.API_ERROR_241012);
        }
        FileldPojo secondFileldPojo = secondFieldJson.toJavaObject(FileldPojo.class);
        slaveSourceList.get(i).setLinkAttrCopy(secondFileldPojo.getAttr());
        slaveSourceList.get(i).setFieldType(secondFileldPojo.getFieldType());
        setInData(slaveSourceList.get(i));
    }


    /**
     * items添加 复制于InitExplainsHelper.setCombItem方法
     * @param str 字段名称
     * @return items
     * @author zhouwq
     * @date 2019/5/27 10:12
     */
    public static List<ItemPoJo> setCombItem(String str){
        List<ItemPoJo> itemPoJoList = new ArrayList<>();
        List<String> stringList = StringUtil.toStringList(str,",");
        int value = 0;
        if(stringList != null) {
            for (String text : stringList) {
                ItemPoJo itemPoJo = new ItemPoJo();
                itemPoJo.setText(text);
                itemPoJo.setValue(Integer.toString(value));
                itemPoJo.setChecked(false);
                if (value == 0) {
                    itemPoJo.setChecked(true);
                }
                itemPoJoList.add(itemPoJo);
                value++;
            }
        }
        return itemPoJoList;
    }

    /**
     * 自定义穿透查询时默认的一些规则条件组装
     * @param chartEntity
     * @param boolQueryBuilder
     * @Author yuqian
     * @date 2019/5/23 9:56
     */
    public void customIndexQueryDefaultFilter(ChartEntity chartEntity,BoolQueryBuilder boolQueryBuilder) throws XbbException{
        if (!ObjectUtils.isEmpty(chartEntity.getChartClassify())) {
            checkProductCategory(chartEntity.getChartClassify(),boolQueryBuilder);
        }
        if (!ObjectUtils.isEmpty(chartEntity.getChartSeries())) {
            checkProductCategory(chartEntity.getChartSeries(),boolQueryBuilder);
        }
        if (!ObjectUtils.isEmpty(chartEntity.getRowGroupAttr())) {
            checkProductCategory(chartEntity.getRowGroupAttr(),boolQueryBuilder);
        }
        if (!ObjectUtils.isEmpty(chartEntity.getColGroupAttr())) {
            checkProductCategory(chartEntity.getColGroupAttr(),boolQueryBuilder);
        }
        JSONObject driverSourcesObject = chartEntity.getDriverSources();
        SlaveSourcePojo driverSourcePojo = JSON.toJavaObject(driverSourcesObject, SlaveSourcePojo.class);
        JSONArray slaveSourcesObject = chartEntity.getSlaveSources();
        JSONObject formIdAttr = chartEntity.getFormIdAttr();
        List<SlaveSourcePojo> slaveSourceList = null;
        if(slaveSourcesObject!=null) {
            slaveSourceList = slaveSourcesObject.toJavaList(SlaveSourcePojo.class);
        }
        if(EsUtil.getSingle(chartEntity)){
            if(driverSourcePojo.getBusinessType()!=null) {
                XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(driverSourcePojo.getBusinessType());
                queryEsDefaultFilter(boolQueryBuilder, xbbRefTypeEnum, null, driverSourcePojo.getFormId());
            }
        }else {
            if(driverSourcePojo.getBusinessType()!=null) {
                XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(driverSourcePojo.getBusinessType());
                queryEsDefaultFilter(boolQueryBuilder, xbbRefTypeEnum, formIdAttr, driverSourcePojo.getFormId());
                for (SlaveSourcePojo slaveSourcePojo : slaveSourceList) {
                    if(slaveSourcePojo.getBusinessType()!=null) {
                        XbbRefTypeEnum xbbRefEnum = XbbRefTypeEnum.getByCode(slaveSourcePojo.getBusinessType());
                        queryEsDefaultFilter(boolQueryBuilder, xbbRefEnum, formIdAttr, slaveSourcePojo.getFormId());
                    }
                }
            }
        }
    }

    private void checkProductCategory(JSONArray allTypeAttr, BoolQueryBuilder boolQueryBuilder) {
        String str = JSONArray.toJSONString(allTypeAttr, SerializerFeature.DisableCircularReferenceDetect);
        List<FieldAttrPojo> fieldAttrPojoList = JSONArray.parseArray(str, FieldAttrPojo.class);
        for (int i = 0; i < fieldAttrPojoList.size(); i++) {
            FieldAttrPojo fieldAttrPojo = fieldAttrPojoList.get(i);
            if (XbbRefTypeEnum.PRODUCT.getCode() == fieldAttrPojo.getBusinessType() && ProductEnum.CATEGORY_ID.getAttr().equals(fieldAttrPojo.getAttr())) {
                JSONArray selectedCategory = fieldAttrPojo.getSelectedCategory();
                if (ObjectUtils.isEmpty(selectedCategory)) {
                    return;
                }
                List<Double> doubleList=new ArrayList<>();
                for (int j = 0; j < selectedCategory.size(); j++) {
                    JSONObject jsonObject = selectedCategory.getJSONObject(j);
                    doubleList.add(jsonObject.getDoubleValue("id"));
                }
                boolQueryBuilder.filter(termsQuery("data.num_13",doubleList));
                //boolQueryBuilder.filter(termQuery("data.num_4",1.0));
            }
        }
    }

    /**
     * 查询时默认的一些规则条件组装
     * @param boolQueryBuilder
     * @param xbbRefTypeEnum
     * @throws XbbException
     */
    private void queryEsDefaultFilter(BoolQueryBuilder boolQueryBuilder, XbbRefTypeEnum xbbRefTypeEnum, JSONObject formIdAttr, Long formId)throws XbbException{
        String data = "data.";
        StringBuilder stringBuilder = new StringBuilder();
        switch (xbbRefTypeEnum){
            case CONTRACT:
                //红冲合同不展示
                if (formIdAttr != null && formIdAttr.size() > 0) {
                    stringBuilder.append(formIdAttr.getJSONObject(formId.toString()).getString(ContractEnum.IS_RED.getAttr()));
                } else {
                    stringBuilder.append(data).append(ContractEnum.IS_RED.getAttr());
                }
                boolQueryBuilder.filter(termQuery(stringBuilder.toString(),0));
                break;
            case PRODUCT:
                //多表时不考虑
                if(formIdAttr == null || formIdAttr.size() == 0) {
                    List<ConditionsEntityExt> conditionsEntityExtList = new ArrayList<>();
                    //只查子产品
                    conditionsEntityExtList.add(new ConditionsEntityExt(ProductEnum.PARENT_ID.getAttr(), "", FieldTypeEnum.NUM.getType(), ConditionEnum.NOEQUAL.getSymbol(), Collections.singletonList(0)));
                    EsUtil.parseCondition(boolQueryBuilder, conditionsEntityExtList, null, null, null);
                }
                break;
            case WORK_ORDER:
                //多表展示不考虑
                if(formIdAttr == null || formIdAttr.size() == 0){
                    List<ConditionsEntityExt> conditionsEntityExtList = new ArrayList<>();
                    ConditionsEntityExt  conditionsEntityExt = new ConditionsEntityExt();
                    conditionsEntityExt.setAttr(FieldTypeEnum.WORK_ORDER_ROB.getAlias());
                    conditionsEntityExt.setFieldType(FieldTypeEnum.WORK_ORDER_ROB.getType());
                    conditionsEntityExt.setSymbol(ConditionEnum.EQUAL.getSymbol());
                    conditionsEntityExt.setValue(Collections.singletonList(WorkOrderTypeEnum.NORMAL.getCode()));
                    conditionsEntityExtList.add(conditionsEntityExt);
                    EsUtil.parseCondition(boolQueryBuilder,conditionsEntityExtList,null,null,null);
                }
                break;
            case CUSTOMER_COMMUNICATE:
                //跟进记录多表已经在数据端处理
                //过滤项目日志
                if(formIdAttr == null || formIdAttr.size() == 0) {
                    stringBuilder.append(data);
                    stringBuilder.append(CustomerCommunicateEnum.AUTO_GEN.getAttr());
                    boolQueryBuilder.filter(termQuery(stringBuilder.toString(), BasicConstant.ZERO));
                }
                break;
            case PAYMENT_SHEET:
            case WRITE_OFF_PREPAYMENT:
            case RED_PAYMENT_SHEET:
            case RED_PREPAYMENT:
            case RED_WRITE_OFF_PREPAYMENT:
            case RED_WRITE_OFF_BALANCE:
            case PREPAYMENT:
            case BAD_DEBT:
            case PAY_SHEET:
            case WRITE_OFF_PREPAY:
            case RED_WRITE_OFF_PAY:
            case RED_PREPAY:
            case RED_WRITE_OFF_PREPAY:
            case PREPAY:
            case BAD_PAY:
                List<Integer> sheetTypeList = null;
                if (formIdAttr != null && formIdAttr.size() > 0) {
                    sheetTypeList = SheetAloneEnum.getNotParentCodeList();
                    stringBuilder.append(formIdAttr.getJSONObject(formId.toString()).getString(FieldTypeEnum.SHEET_ALONE.getAlias()));
                }else {
                    stringBuilder.append(FieldTypeEnum.SHEET_ALONE.getAlias());
                    sheetTypeList = SheetAloneEnum.getNotChildCodeList();
                }
                boolQueryBuilder.filter(termsQuery(stringBuilder.toString(),sheetTypeList));
                break;
            default:
                break;
        }
        //多表的默认值
        if (formIdAttr != null && formIdAttr.size() > 0) {
            boolQueryBuilder.filter(termQuery(formIdAttr.getJSONObject(formId.toString()).getString("del"),0));
            if(Objects.equals(xbbRefTypeEnum.getCode(),XbbRefTypeEnum.CONTRACT_PERFORMANCE.getCode())
                    || Objects.equals(xbbRefTypeEnum.getCode(),XbbRefTypeEnum.CONTRACT_PRODUCT.getCode())
                    || Objects.equals(xbbRefTypeEnum.getCode(),XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode())) {
                return;
            }
            boolQueryBuilder.filter(termsQuery(formIdAttr.getJSONObject(formId.toString()).getString(BiEsAliasEnum.FLOWSTATUS.getEsAlias()),Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        }
    }

    /**
     * 封装映射关系
     * @param jsonObject 字段属性
     * @param selectedMap   选中的字段
     * @param selectedByFormIdMap   选中的字段按照formId归集
     * @param accumulatorPojo 累加器
     * @return attr
     */
    private static String handleAttrMapping(JSONObject jsonObject, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo) {
        //判断是否是计算字段
        if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(),jsonObject.getInteger("fieldType"))) {
            return "";
        }else{
            BiExplainPojo biExplainPojo = jsonObject.toJavaObject(BiExplainPojo.class);
            String attr = reflectAttr(biExplainPojo, selectedMap, selectedByFormIdMap, accumulatorPojo);
            jsonObject.put("attr", attr);
            jsonObject.put("originalAttr", biExplainPojo.getOriginalAttr());
            return attr;
        }
    }

    /**
     * 封装映射关系
     * @param biExplainPojo 字段属性
     * @param selectedMap   选中的字段
     * @param selectedByFormIdMap   选中的字段按照formId归集
     * @param accumulatorPojo 累加器
     * @return java.lang.String
     * @since v1.0
     * @version v1.0
     */
    public static String reflectAttr(BiExplainPojo biExplainPojo, Map<String, Object> selectedMap, Map<String, Map<String, String>> selectedByFormIdMap, AccumulatorPojo accumulatorPojo) {
        String originalAttr = biExplainPojo.getOriginalAttr();
        //original如果存在（不包括“”）则证明已经处理过属于编辑
        originalAttr = StringUtil.isNotEmpty(originalAttr)?originalAttr:biExplainPojo.getAttr();
        //使用中划线，后面易于和原有字段内的下划线
        String key = originalAttr + "-" + biExplainPojo.getFormId();
        String attr = "";
        //根据formId
        Long formId = biExplainPojo.getFormId();
        Map<String, String> attrKeyMap = null;
        try {
            if (Objects.nonNull(formId)) {
                attrKeyMap = selectedByFormIdMap.get(formId.toString());
            }
        } catch (Exception e) {
            LOG.error("=======" + selectedByFormIdMap + "======" + formId + "=====" + biExplainPojo, e);
        }
        biExplainPojo.setOriginalAttr(originalAttr);
        //防重复
        if (selectedMap.get(key) != null) {
            Object value = selectedMap.get(key);
            JSONObject jsonValue = JSON.parseObject(value.toString());
            BiExplainPojo biExplainPojoValue = jsonValue.toJavaObject(BiExplainPojo.class);
            attr = biExplainPojoValue.getAttr();
            biExplainPojo.setAttr(attr);
        } else {
            Set<String> productLinkMainBusiness = BIProductReformEnum.getAllDbFieldLinkMainBusiness();
            productLinkMainBusiness.add(StringConstant.PRODUCT_ID);
            //此处直接使用attr判断，使用fieldType要再找一次不如直接判断简单
            if (originalAttr.contains(EsAliasEnum.TEXT.getEsAlias())) {
                //TODO 这里要去判断MAX值
                attr = EsAliasEnum.TEXT.getEsAlias() + "_" + accumulatorPojo.getTextAccum();
            } else if (originalAttr.contains(EsAliasEnum.NUM.getEsAlias())) {
                attr = EsAliasEnum.NUM.getEsAlias() + "_" + accumulatorPojo.getNumAccum();
            } else if (originalAttr.contains(EsAliasEnum.LONG.getEsAlias())) {
                attr = EsAliasEnum.LONG.getEsAlias() + "_" + accumulatorPojo.getLongNum();
            } else if (originalAttr.contains(EsAliasEnum.ADDRESS.getEsAlias()) || originalAttr.contains(EsAliasEnum.GEO.getEsAlias()) || originalAttr.contains(EsAliasEnum.LOCATION.getEsAlias())) {
                attr = handleAddressAttr(originalAttr, attrKeyMap, accumulatorPojo);
            } else if (originalAttr.contains(EsAliasEnum.DATE.getEsAlias())) {
                attr = EsAliasEnum.DATE.getEsAlias() + "_" + accumulatorPojo.getDateAccum();
            } else if (originalAttr.contains(EsAliasEnum.SUB_FORM.getEsAlias())) {
                attr = EsAliasEnum.SUB_FORM.getEsAlias() + "_" + accumulatorPojo.getSubFormAccum();
            } else if (originalAttr.contains(EsAliasEnum.FILE.getEsAlias())) {
                attr = EsAliasEnum.FILE.getEsAlias() + "_" + accumulatorPojo.getFileAccum();
            } else if (originalAttr.contains(EsAliasEnum.ARRAY.getEsAlias())) {
                attr = EsAliasEnum.ARRAY.getEsAlias() + "_" + accumulatorPojo.getArrayAccum();
            } else if (originalAttr.contains("Time")) {
                //时间类的处理，归集到date里,例如
                attr = EsAliasEnum.DATE.getEsAlias() + "_" + accumulatorPojo.getDateAccum();
            } else if (originalAttr.contains(BiEsAliasEnum.FORMID.getEsAlias())) {
                attr = BiEsAliasEnum.FORMID.getEsAlias() + "_" + accumulatorPojo.getFormIdAccum();
            } else if (originalAttr.contains(BiEsAliasEnum.SERIALNO.getEsAlias())) {
                //流水号放到text里面
                attr = BiEsAliasEnum.TEXT.getEsAlias() + "_" + accumulatorPojo.getTextAccum();
            } else if (originalAttr.contains(BiEsAliasEnum.OWNERID.getEsAlias())) {
                attr = BiEsAliasEnum.OWNERID.getEsAlias() + "_" + accumulatorPojo.getOwnerIdAccum();
            } else if (originalAttr.contains(FieldTypeEnum.COUSERID.getAlias())) {
                attr = FieldTypeEnum.COUSERID.getAlias() + "_" + accumulatorPojo.getCoUserIdAccum();
            }else if (originalAttr.contains(BiEsAliasEnum.DEPARTMENTID.getEsAlias())) {
                attr = BiEsAliasEnum.DEPARTMENTID.getEsAlias() + "_" + accumulatorPojo.getDepartmentIdAccum();
            } else if (originalAttr.contains(BiEsAliasEnum.FLOWSTATUS.getEsAlias())) {
                attr = BiEsAliasEnum.FLOWSTATUS.getEsAlias() + "_" + accumulatorPojo.getFlowStatusAccum();
            } else if (originalAttr.contains(BiEsAliasEnum.STATUS.getEsAlias())) {
                attr = BiEsAliasEnum.STATUS.getEsAlias() + "_" + accumulatorPojo.getFlowStatusAccum();
            } else if (originalAttr.contains(BiEsAliasEnum.CREATORID.getEsAlias())) {
                attr = BiEsAliasEnum.CREATORID.getEsAlias() + "_" + accumulatorPojo.getCreatorIdAccum();
            } else if (originalAttr.contains(BiEsAliasEnum.DATAID.getEsAlias())) {
                attr = BiEsAliasEnum.DATAID.getEsAlias() + "_" + accumulatorPojo.getDataIdAccum();
            } else if(originalAttr.contains(BiEsAliasEnum.ID.getEsAlias())){
                attr = BiEsAliasEnum.ID.getEsAlias() + "_" + accumulatorPojo.getIdAccum();
            } else if(originalAttr.contains("del")){
                attr = EsAliasEnum.NUM.getEsAlias() + "_" + accumulatorPojo.getNumAccum();
            } else if(originalAttr.contains(FieldTypeEnum.SHEET_ALONE.getAlias())){
                attr = EsAliasEnum.NUM.getEsAlias() + "_" + accumulatorPojo.getNumAccum();
            } else if(productLinkMainBusiness.contains(originalAttr) ||originalAttr.contains("otherId")){
                //其他的id后面统一加在这里
                attr = "otherId" + "_" + accumulatorPojo.getOtherIdNum();
            } else if (Objects.equals(BasicConstant.ZERO_LONG, biExplainPojo.getFormId()) && WorkOrderV2NodeLogInfoEnum.getAllAttr().contains(originalAttr)){
                //工单2.0LogInfo表Data外字段特殊逻辑
                List<String> timeField = WorkOrderV2NodeLogInfoEnum.getAttrByFieldType(FieldTypeEnum.DATETIME.getType());
                List<String> numField = WorkOrderV2NodeLogInfoEnum.getAttrByFieldType(FieldTypeEnum.NUM.getType());
                if(timeField.contains(originalAttr)){
                    attr = EsAliasEnum.DATE.getEsAlias() + "_" + accumulatorPojo.getDateAccum();
                }else if (numField.contains(originalAttr)){
                    attr = EsAliasEnum.NUM.getEsAlias() + "_" + accumulatorPojo.getNumAccum();
                }else{
                    attr = EsAliasEnum.TEXT.getEsAlias() + "_" + accumulatorPojo.getTextAccum();
                }
            } else {
                //TODO
                //例如corpid不需要归集的字段
                attr = originalAttr;
            }
            biExplainPojo.setAttr(attr);
            selectedMap.put(key, JSON.toJSON(biExplainPojo));
            if (attrKeyMap != null) {
                if (!attrKeyMap.containsKey(originalAttr)) {
                    attrKeyMap.put(originalAttr, attr);
                }
            } else {
                attrKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                attrKeyMap.put(originalAttr, attr);
            }
            selectedByFormIdMap.put(formId.toString(), attrKeyMap);
        }
        return attr;
    }

    /**
     * 地址字段处理
     * @param originalAttr 字段原始attr
     * @param attrKeyMap 原始字段和新字段attr映射关系
     * @param accumulatorPojo 累加器
     * @return 字段新attr
     * @author zhouwq
     * @date 2020/5/11 10:14
     */
    private static String handleAddressAttr(String originalAttr, Map<String, String> attrKeyMap, AccumulatorPojo accumulatorPojo) {
        String attr = "";
        String[] addressArr = originalAttr.split("\\.");
        if (addressArr.length > 1) {
            if (attrKeyMap != null) {
                //判断attr是否已存在
                boolean existAttr = false;
                for (Map.Entry<String, String> entry : attrKeyMap.entrySet()) {
                    String original = entry.getKey();
                    String newAttr = entry.getValue();
                    if (original.startsWith(addressArr[0])) {
                        String[] address = newAttr.split("\\.");
                        attr = address[0] + StringConstant.POINT + addressArr[1];
                        existAttr = true;
                        break;
                    }
                }
                if (!existAttr) {
                    attr = EsAliasEnum.LOCATION.getEsAlias() + "_" + accumulatorPojo.getLocationAccum();
                    attr = attr + StringConstant.POINT + addressArr[1];
                }
            } else {
                attr = EsAliasEnum.LOCATION.getEsAlias() + "_" + accumulatorPojo.getLocationAccum();
                attr = attr + StringConstant.POINT + addressArr[1];
            }
        } else {
            attr = EsAliasEnum.LOCATION.getEsAlias() + "_" + accumulatorPojo.getLocationAccum();
        }
        return attr;
    }

    public  void backAttr(ChartEntity chartEntity) {
        JSONArray displayArray = chartEntity.getDisplayAttr();
        if(CollectionsUtil.isNotEmpty(displayArray)){
            reBackAttr(displayArray);
            chartEntity.setDisplayAttr(displayArray);
        }
        JSONArray rowGroupAttr = chartEntity.getRowGroupAttr();
        if(CollectionsUtil.isNotEmpty(rowGroupAttr)){
            reBackAttr(rowGroupAttr);
            chartEntity.setRowGroupAttr(rowGroupAttr);
        }
        JSONArray colGroupAttr = chartEntity.getColGroupAttr();
        if(CollectionsUtil.isNotEmpty(colGroupAttr)){
            reBackAttr(colGroupAttr);
            chartEntity.setColGroupAttr(colGroupAttr);
        }
        JSONArray summaryArray = chartEntity.getSummaryAttr();
        if(CollectionsUtil.isNotEmpty(summaryArray)){
            reBackAttr(summaryArray);
            chartEntity.setSummaryAttr(summaryArray);
        }
        JSONArray chartClassifyArray = chartEntity.getChartClassify();
        if(CollectionsUtil.isNotEmpty(chartClassifyArray)){
            reBackAttr(chartClassifyArray);
            chartEntity.setChartClassify(chartClassifyArray);
        }
        JSONArray chartSeriesArray = chartEntity.getChartSeries();
        if(CollectionsUtil.isNotEmpty(chartSeriesArray)){
            reBackAttr(chartSeriesArray);
            chartEntity.setChartSeries(chartSeriesArray);
        }
        JSONArray chartValueArray = chartEntity.getChartValue();
        if(CollectionsUtil.isNotEmpty(chartValueArray)){
            reBackAttr(chartValueArray);
            chartEntity.setChartValue(chartValueArray);
        }
        JSONArray penetrateArray = chartEntity.getPenetrateAttr();
        if(CollectionsUtil.isNotEmpty(penetrateArray)){
            reBackAttr(penetrateArray);
            chartEntity.setPenetrateAttr(penetrateArray);
        }
        JSONArray searchArray = chartEntity.getSearch();
        if(CollectionsUtil.isNotEmpty(searchArray)){
            reBackAttr(searchArray);
            chartEntity.setSearch(searchArray);
        }
        JSONArray filterArray = chartEntity.getFilter();
        if(CollectionsUtil.isNotEmpty(filterArray)){
            reBackAttr(filterArray);
            chartEntity.setFilter(filterArray);
        }
    }
    /**
     * 把钻取内原来映射过的字段恢复为原attr（多表场景映射，后面因为负责人等字段移除变为单表需要恢复attr）
     * @param chartEntity
     * @param drill
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void backAttr(ChartEntity chartEntity, JSONArray drill){
        if (CollectionsUtil.isEmpty(drill)) {
            return;
        }
        for (int i = 0; i < drill.size(); i++) {
            JSONObject jsonObject = drill.getJSONObject(i);
            JSONArray field = jsonObject.getJSONArray(BusinessConstant.FIELD);
            if (CollectionUtils.isEmpty(field)) {
                continue;
            }
            reBackAttr(field);
            drill.set(i, jsonObject);
        }
        chartEntity.setDrill(drill);
    }

    private  void reBackAttr(JSONArray displayArray) {
        if(CollectionsUtil.isNotEmpty(displayArray)){
            for (int i = 0; i < displayArray.size(); i++) {
                JSONObject jsonObject = displayArray.getJSONObject(i);
                String originalAttr=  jsonObject.getString("originalAttr");
                if(StringUtil.isNotEmpty(originalAttr)){
                    jsonObject.put("attr",originalAttr);
                }
                Integer fieldType  = jsonObject.getInteger("fieldType");
                if (FieldTypeEnum.LINK_BUSINESS_SINGLE.getType().equals(fieldType) || FieldTypeEnum.LINK_BUSINESS_MULTI.getType().equals(fieldType) || FieldTypeEnum.BIRTHDAY.getType().equals(fieldType)) {
                    JSONObject linkedAttr = jsonObject.getJSONObject("linkedAttr");
                    if(linkedAttr != null){
                        String linkOriginalAttr = linkedAttr.getString("originalAttr");
                        if(StringUtil.isNotEmpty(linkOriginalAttr)){
                            linkedAttr.put("attr",linkOriginalAttr);
                            jsonObject.put("linkedText", linkOriginalAttr);
                        }
                    }
                }
                //覆盖回去
                displayArray.set(i,jsonObject);
            }
        }
    }


    /**
     * 全局权限控制 (新建，编辑，删除)
     * @param baseDTO 入参
     * @author zhouwq
     * @date 2019/5/6 15:59
     */
    public JSONObject chartOverallPermissions(BaseDTO baseDTO){
        //当前用户的权限
        UserVO userVO = baseDTO.getLoginUser();
        // 查看和打印的权限 需要在单个图表内进行二次权限控制
        JSONObject chartPermissionObj = new JSONObject();
        chartPermissionObj.put(ChartProPermissionAliasEnum.CHART_EXPORT.getAlias(),ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_EXPORT.getAlias()));
        chartPermissionObj.put(ChartProPermissionAliasEnum.CHART_UPDATE.getAlias(),ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_UPDATE.getAlias()));
        chartPermissionObj.put(ChartProPermissionAliasEnum.CHART_ADD.getAlias(),ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_ADD.getAlias()));
        chartPermissionObj.put(ChartProPermissionAliasEnum.CHART_PUBLISH.getAlias(),ProPermissionHelp.hasThisPermission(userVO, ChartProPermissionAliasEnum.CHART_PUBLISH.getAlias()));
        return chartPermissionObj;
    }

    /**
     * 是否可见 权限控制
     * @param object 针对单个chart设置的权限
     * @param baseDTO 入参
     * @param overAllPermissions 全局权限信息
     * @param subAllDepIdMap 部门ID对应子部门ID映射关系
     * @author zhouwq
     * @date 2019/5/1 14:10
     * @return false 无权限 true 有权限
     */
    public Map<String, Boolean> isChartPermissions(JSONObject object, BaseDTO baseDTO, JSONObject overAllPermissions, Map<Long, List<Long>> subAllDepIdMap){
        Map<String, Boolean> permissions = new HashMap<>(2);

        //当前用户的权限
        UserVO userVO = baseDTO.getLoginUser();
        Set<RoleSimpleVO> roleSet = userVO.getRoleSet();
        Set<DepartmentVO> depSet = userVO.getDepSet();

        //若判断该用户为管理员权限直接返回
        if(userVO.isAdminOrBoss()) {
            permissions.put(ChartProPermissionAliasEnum.CHART_VIEW.getAlias(), true);
            permissions.put(ChartProPermissionAliasEnum.CHART_UPDATE.getAlias(), true);
            permissions.put(ChartProPermissionAliasEnum.CHART_ADD.getAlias(), true);
            permissions.put(ChartProPermissionAliasEnum.CHART_EXPORT.getAlias(), true);
            permissions.put(ChartProPermissionAliasEnum.CHART_PUBLISH.getAlias(), true);
            return permissions;
        }

        //判断用户是否具有可见权限
        Boolean viewPermission = false;
        //判断用户是否具有可导出权限
        Boolean exportPermission = overAllPermissions.getBoolean(ChartProPermissionAliasEnum.CHART_EXPORT.getAlias());
        //判断用户是否具有编辑权限
        Boolean updatePermission = overAllPermissions.getBoolean(ChartProPermissionAliasEnum.CHART_UPDATE.getAlias());
        //判断用户是否具有新建权限
        Boolean addPermission = overAllPermissions.getBoolean(ChartProPermissionAliasEnum.CHART_ADD.getAlias());

        //有新建或编辑权限 则可查看所有图表
        if(updatePermission || addPermission){
            viewPermission = true;
        }

        if(object != null && object.size() > 0) {
            ChartPermissionsPojo entity = JSONObject.parseObject(object.toJSONString(), ChartPermissionsPojo.class);
            Set<Long> depIdIn = getSubDepIds(depSet, subAllDepIdMap);
            //判断是否可见权限
            Integer visibleType = entity.getVisible();
            if (!viewPermission) {
                if(ChartPermissionsTypeEnum.IS_ABLE.getType().equals(visibleType)) {
                    Integer visibleAdvanced = entity.getVisibleScopeEnable();
                    if(visibleAdvanced == null || ChartPermissionsTypeEnum.NOT_IS_ABLE.getType().equals(visibleAdvanced)){
                        viewPermission = true;
                    }else{
                        viewPermission = chartPermissionHelp.permissionsDetailsJudge(entity.getVisibleScopeRule(),roleSet,depIdIn,baseDTO.getUserId());
                    }
                }
            }

            //判断是否可导出权限
            exportPermission = getExportPermission(baseDTO, exportPermission, entity, depIdIn);
        }
        permissions.put(ChartProPermissionAliasEnum.CHART_VIEW.getAlias(),viewPermission);
        permissions.put(ChartProPermissionAliasEnum.CHART_EXPORT.getAlias(),exportPermission);
        permissions.put(ChartProPermissionAliasEnum.CHART_PUBLISH.getAlias(),overAllPermissions.getBoolean(ChartProPermissionAliasEnum.CHART_PUBLISH.getAlias()));

        return permissions;
    }

    /**
     * 判断是否可导出权限
     * @param baseDTO
     * @param exportPermission
     * @param chartPermissionsPojo
     * @param depIdIn
     * @return java.lang.Boolean
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2021/5/26 18:29
     * @version 1.0
     */
    public Boolean getExportPermission(BaseDTO baseDTO, Boolean exportPermission, ChartPermissionsPojo chartPermissionsPojo, Set<Long> depIdIn) {
        Integer exportType = chartPermissionsPojo.getExport();
        ChartPermissionDetailsPojo exportRule = chartPermissionsPojo.getExportRule() == null ? new ChartPermissionDetailsPojo() : chartPermissionsPojo.getExportRule();
        if(exportPermission && !Objects.equals(exportRule.getType(), VisibleTypeEnum.NOT_SHOW_ANYONE.getType())){
            exportPermission = true;
        }else if(ChartPermissionsTypeEnum.IS_ABLE.getType().equals(exportType)){
            Integer exportAdvanced = chartPermissionsPojo.getExportAdvanceEnable();
            if(exportAdvanced == null || ChartPermissionsTypeEnum.NOT_IS_ABLE.getType().equals(exportAdvanced)){
                exportPermission = true;
            }else{
                exportPermission = chartPermissionHelp.permissionsDetailsJudge(exportRule, baseDTO.getLoginUser().getRoleSet(), depIdIn, baseDTO.getUserId());
            }
        }
        return exportPermission;
    }

    /**
     * 判断分类可见权限
     * @param object 单个分类中的权限
     * @param baseDTO 入参
     * @param subAllDepIdMap 部门ID对应子部门ID映射关系
     * @return true 可见 false 不可见
     * @author zhouwq
     * @date 2020/8/31 10:06
     */
    public boolean judgeCategoryPermissions(JSONObject object, BaseDTO baseDTO, Map<Long, List<Long>> subAllDepIdMap) {
        //当前用户的权限
        UserVO userVO = baseDTO.getLoginUser();
        Set<RoleSimpleVO> roleSet = userVO.getRoleSet();
        Set<DepartmentVO> depSet = userVO.getDepSet();
        if (userVO.isAdminOrBoss()) {
            return true;
        }
        if (object != null) {
            ChartPermissionsPojo entity = JSONObject.parseObject(object.toJSONString(), ChartPermissionsPojo.class);
            Set<Long> depIdIn = getSubDepIds(depSet, subAllDepIdMap);
            //判断是否可见权限
            Integer visibleType = entity.getVisible();
            if (ChartPermissionsTypeEnum.IS_ABLE.getType().equals(visibleType)) {
                Integer visibleAdvanced = entity.getVisibleScopeEnable();
                if (visibleAdvanced == null || ChartPermissionsTypeEnum.NOT_IS_ABLE.getType().equals(visibleAdvanced)) {
                    return true;
                } else {
                    return chartPermissionHelp.permissionsDetailsJudge(entity.getVisibleScopeRule(), roleSet, depIdIn, userVO.getUserId());
                }
            }
        }
        return false;
    }

    /**
     * 获取子部门ID以及自身所属部门ID集合
     * @param depSet 自身所属部门ID
     * @param subAllDepIdMap 下级部门mapping关系
     * @return Long
     * @author zhouwq
     * @date 2020/9/7 14:16
     */
    public static Set<Long> getSubDepIds(Set<DepartmentVO> depSet, Map<Long, List<Long>> subAllDepIdMap) {
        Set<Long> depIdIn = new HashSet<>();
        depSet.forEach(departmentVO -> depIdIn.add(departmentVO.getId()));
        //部门以及所有下级部门
        Set<Long> depLists = new HashSet<>();
        depIdIn.forEach(e -> {
            List<Long> subIds = subAllDepIdMap.get(e);
            if (subIds != null) {
                depLists.addAll(subIds);
            }
        });
        depIdIn.addAll(depLists);
        return depIdIn;
    }

    /**
     * 自定义图表数据查询
     * @param chartEntity 图表实体
     * @param isWarningSync 是否预警
     * @author yuqian
     * @date 2019/3/28 10:58
     * @since v1.0
     */
    public void chartDataEsQuery(ChartEntity chartEntity, SearchSourceBuilder sourceBuilder, BoolQueryBuilder boolQueryBuilder, SearchRequest searchRequest, BaseDTO baseDTO, Boolean isWarningSync) throws XbbException {
        boolQueryBuilder.filter(termQuery("corpid.keyword", chartEntity.getCorpid()));
        sourceBuilder.query(boolQueryBuilder);
        //获取主数据源和从数据源
        JSONObject driverSourcesObject = chartEntity.getDriverSources();
        if (Objects.isNull(isWarningSync) || !isWarningSync){
            setPermission(chartEntity, baseDTO);
        }
        SlaveSourcePojo driverSourcePojo = JSON.toJavaObject(driverSourcesObject, SlaveSourcePojo.class);
        //从数据表，多表数据源
        if (Objects.equals(chartEntity.getMuti(),0)) {
            BiRelTableEnum biRelTableEnum = getBiRelTableEnum(driverSourcePojo.getBusinessType(), driverSourcePojo.getSaasMark());
            List<BiProWareEntity> list = biProWareService.getBiProWareEntities(chartEntity);
            if (CollectionsUtil.isNotEmpty(list)) {
                if (Objects.equals(list.get(0).getIsDone(), 0)) {
                    throw  new XbbException(BiErrorCodeEnum.API_ERROR_241013);
                }else {
                    //isDone =1 但是考虑mq和logstash的时间
                    String value = paasRedisHelper.getValue(RedisPrefixConstant.BUILD_WARE_FLAG_ONE_MIN, chartEntity.getCorpid() + "_" + chartEntity.getId());
                    // 无查询条件时存缓存
                    if (StringUtil.isNotEmpty(value)) {
                        throw  new XbbException(BiErrorCodeEnum.API_ERROR_241013);
                    }
                }
                boolQueryBuilder.filter(termQuery(BiConstant.WAREHOUSE_ID, list.get(0).getId()));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,biRelTableEnum.getType()));
                searchRequest.indices(biRelTableEnum.getIndex());
            }else {
                LOG.error("===warehouseId查不到");
                throw  new XbbException(BiErrorCodeEnum.API_ERROR_241013);
            }
        } else {
            //单表
            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(chartEntity.getCorpid(), driverSourcePojo.getBusinessType(), driverSourcePojo.getSaasMark());
            searchRequest.indices(indexTypeEnum.getIndex());
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
            boolQueryBuilder.filter(termQuery("formId", driverSourcePojo.getFormId()));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            if (IndexTypeEnum.IDX_SAAS_DISTRIBUTOR_ACCOUNT == indexTypeEnum
                    || IndexTypeEnum.IDX_SAAS_MARKETING_ACTIVITY_MANAGEMENT == indexTypeEnum
                    || IndexTypeEnum.IDX_SAAS_PROMOTION_ACTIVITY_MANAGEMENT == indexTypeEnum){
                return;
            }
            // 跟进记录不需要flowStatus条件，性能问题 by kaka
            if (!IDX_SAAS_CUSTOMER_COMMUNICATE.getCode().equals(indexTypeEnum.getCode())) {
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
            }
        }
    }

    /**
     * 设置登录查看权限
     * @param chartEntity
     * @param baseDTO
     */
    public void setPermission(ChartEntity chartEntity, BaseDTO baseDTO) {
        UserVO userVO = baseDTO.getLoginUser();
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        JSONObject dataPermissionAttr = null;
        JSONArray searchArray = chartEntity.getSearch();
        boolean isMaxDataPermission = userVO.isMaxDataPermission(true);
        List<String> userIdIn;
        if (!isMaxDataPermission) {
            JSONObject permission = chartEntity.getPermissions();
            //数据权限字段
            dataPermissionAttr = permission == null ? null : permission.getJSONObject("dataPermissionAttr");
            if (dataPermissionAttr != null && !dataPermissionAttr.isEmpty()) {
                Integer dataPermission;
                if (ChartSourceEnum.isDataSet(chartEntity.getSingle())) {
                    // 当数据集图表设计为数据表单权限的时候，需要加载组织权限作为数据权限
                    dataPermission = userModel.getDataPermission(userEntity, true);
                } else {
                    dataPermission = userModel.getDataPermission(userEntity);
                }
                // 当图表设计为数据表单权限的时候，非管理员角色需要查看到离职人员的数据
                userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userVO.getUserId(), userVO.getCorpid(), BasicConstant.ONE, false);
                dataPermissionAttr.put("symbol", ConditionEnum.INCLUDE.getSymbol());
                dataPermissionAttr.put("value", userIdIn);
                searchArray.add(dataPermissionAttr);
                chartEntity.setSearch(searchArray);
            }
        }
    }

    /**
     * 将ChaTypeEnum转换成vo
     *
     * @param chartTypeEnumList   图表类型枚举
     * @return java.util.List<com.xbongbong.pro.statistic.pojo.ChartTypeMemoPojo>
     * @author zyy
     * @date 2022/4/14
     * @version v1.0
     */
    public List<ChartTypeMemoPojo> getChartMemo(List<ChartTypeEnum> chartTypeEnumList) {
        List<ChartTypeMemoPojo> chartTypeMemoList = new ArrayList<>();
        chartTypeEnumList.forEach(var -> {
            ChartTypeMemoPojo chartTypeMemo = new ChartTypeMemoPojo();
            chartTypeMemo.setCode(var.getCode());
            chartTypeMemo.setMemo(var.getMemo());
            chartTypeMemoList.add(chartTypeMemo);
        });
        return chartTypeMemoList;
    }

    /**
     * 图表单位中英文转换
     *
     * @param chartEntity 图表实体
     * @author zyy
     * @date 2022/7/19
     * @version v1.0
     */
    public void unitConversion(ChartEntity chartEntity) {
        // 单位转换
        if (chartEntity.getNumFormat() != null && Objects.equals(chartEntity.getUnit(), UnitEnum.MONEY.getAlias())) {
            // 数值格式单位转换，只有当选择"元"并且选了数值格式的时候才需要
            NumFormatEnum numFormatEnum = NumFormatEnum.getByCode(chartEntity.getNumFormat());
            String unit = numFormatEnum.getUnit();
            chartEntity.setUnit(unit);
        } else {
            //自定义单位转换中文,一定要放在数据获取后
            String unit = setUnit(chartEntity);
            chartEntity.setUnit(unit);

        }
    }

    /**
     * 是否可钻取
     * @param corpid
     * @param permSet
     * @return boolean true 有钻取开关
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public boolean drillPermission(String corpid, Set<String> permSet) throws XbbException {
        boolean ckFlag = chartLimitService.getCkFlag();
        //ck才支持钻取
        if (ckFlag) {
            // 旗舰版才有钻取开关
            Boolean isUltimate = Objects.equals(packageHelp.getFeeType(corpid), PackageTypeEnum.ULTIMATE.getType());
            if (isUltimate) {
                //ck、旗舰版、且有钻取权限，则有钻取开关
                return permSet.contains(ProPermissionAliasEnum.CHART_DRILL.getAlias());
            }
        }
        return false;
    }

    /**
     * 处理钻取信息
     * @param corpid
     * @param chartResultDTO
     * @return com.xbongbong.pro.statistic.result.pojo.DrillResultPojo
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public DrillResultPojo formatDrillMap(String corpid, ChartResultDTO chartResultDTO, List<ChartEntity> chartEntityList) throws XbbException {
        //非自定义图表不处理钻取
        List<Long> customIdIn = chartResultDTO.getCustomIdIn();
        return formatDrillMap(corpid, chartResultDTO, customIdIn, chartEntityList);
    }
    /**
     * 处理钻取信息
     * @param corpid
     * @param chartResultDTO
     * @param customIdIn 自定义图表id
     * @return com.xbongbong.pro.statistic.result.pojo.DrillResultPojo
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public DrillResultPojo formatDrillMap(String corpid, ChartResultDTO chartResultDTO, List<Long> customIdIn, List<ChartEntity> chartEntityList) throws XbbException {
        DrillResultPojo drillResultPojo = new DrillResultPojo();
        if (CollectionsUtil.isEmpty(customIdIn)) {
            return drillResultPojo;
        }
        //钻取每次肯定都只一张图，所以只读取1个
        Long chartId = customIdIn.get(0);
        //先查钻取层级配置信息，因为图表默认页肯定是未钻取场景，但是这种情况也需要拿到层级信息去做钻取匹配规则（渲染+号）
        ChartDrillEntity chartDrillEntity = chartDrillModel.getByChartId(corpid, StatisticsTypeEnum.CUSTOM_STATISTIC.getCode(), chartId);
        if (Objects.isNull(chartDrillEntity)) {
            return drillResultPojo;
        }
        List<ChartDrillItemPojo> drillList = JsonHelperUtil.parseArray(JSON.toJSONString(chartDrillEntity.getDrill()), ChartDrillItemPojo.class);
        if (CollectionUtils.isEmpty(drillList)) {
            return drillResultPojo;
        }
        //key：chartId；value：某张图的总钻取信息pojo
        Map<Long, DrillResultChartInfoPojo> resultChartInfoMap = Maps.newHashMapWithExpectedSize(BasicConstant.ONE);
        DrillResultChartInfoPojo drillResultChartInfoPojo = new DrillResultChartInfoPojo(drillList);
        resultChartInfoMap.put(chartId, drillResultChartInfoPojo);
        drillResultPojo.setResultChartInfoMap(resultChartInfoMap);
        //前端传入的钻取信息，如果为空则代表无钻取。key:字段，value钻取字段及条件
        Map<String, ChartDrillInfoPojo> drill = chartResultDTO.getDrill();
        if (Objects.isNull(drill) || drill.isEmpty()) {
            return drillResultPojo;
        }
        Set<String> uuidList = new HashSet<>();
        //key：钻取字段所属层级uuid；value：钻取方向（上卷、下钻）、钻取图表字段（分类、系列、行列）、当前钻取字段及其所属层级attrList等信息pojo
        Map<String, DrillResultChartFieldInfoPojo> uuidFieldMap = Maps.newHashMapWithExpectedSize(drill.size());
        //key：钻取图表的哪个字段（分类、系列、行列）；value：钻取方向（上卷、下钻）、钻取图表字段（分类、系列、行列）、当前钻取字段及其所属层级attrList等信息pojo
        Map<String, DrillResultChartFieldInfoPojo> chartFieldInfoMap = Maps.newHashMapWithExpectedSize(drill.size());
        List<FieldAttrPojo> allCondition = new ArrayList<>();
        //-------------------（1）处理filter，封装当前钻取字段及其所属层级attrList（点击字段进行上卷、下钻，还未转为实际的目标字段，有可能无上级或无下级字段，无法上卷、下钻）等相关信息
        //每次一张图，但是每张图可能存在多个字段属于特殊字段（下钻、上卷处理不同，分开存储）
        List<DrillResultChartFieldInfoPojo> downSpecialList = new ArrayList<>();
        List<DrillResultChartFieldInfoPojo> upSpecialList = new ArrayList<>();
        //标记是否钻取
        boolean noDrill = true;
        for (Map.Entry<String, ChartDrillInfoPojo> entry : drill.entrySet()) {
            ChartDrillInfoPojo value = entry.getValue();
            List<FieldAttrPojo> drillCondition = value.getDrillCondition();
            if (CollectionUtils.isEmpty(drillCondition)) {
                //就算特殊字段的钻取，前端最开始也会默认把部门条件传入，后端会处理成子部门、子分类条件（替换drillCondition内特殊字段value值），所以如果drillCondition为空则该字段未钻取
                continue;
            }
            noDrill = false;
            /*
             当前钻取字段前的字段要转为条件传入（类似统计表穿透时把字段转为条件的逻辑，但是上卷场景需要注意移除部分条件） （注意：统计表无法上卷行列分组之前的字段）
             统计图：当下钻某字段时，其下一级字段会变为新的分类/系列字段，而当前字段会变为新图的筛选条件；而如果下钻多层，则点击的当前钻取字段上至原始的分类/系列字段都需要变为条件传入
             统计表：需要对行分组、列分组分别处理- 钻取时，把当前钻取字段之前至原行分组字段、以及当前列至原列分组字段都转为条件；
             不管上卷还是下钻，drillCondition内最后一个都是当前钻取字段（钻取多个层级后，点击的当前钻取字段和chart本身的分类、系列、行列分组字段【会不一样】，需要通过层级内的字段去匹配到分类、系列、行列进行替换，因为同一个层级肯定只有分类、系列、行列内的一个字段），而条件则根据钻取不同有所区分：
             下钻：drillCondition内所有对象都为条件
             上卷：drillCondition内除最后一个当前钻取字段外，其他的才为条件（如果drillCondition只有1个对象，则代表没有条件，只有当前钻取字段，比如统计图从初始一直上卷）
             */
            //最后一个 - 点击钻取的字段(还不是目标字段-要经过上卷、下钻得到最终的钻取目标字段)
            FieldAttrPojo currentDrillField = drillCondition.get(drillCondition.size() - 1);
            String drillDir = value.getDrillDir();
            boolean up = Objects.equals(drillDir, DrillDirEnum.UP.getAlias());
            if (up) {
                //上卷移除当前钻取字段，剩余的为条件（也是上一次的钻取字段 - 需要强转为表左侧内容，固定到表左侧）
                drillCondition.remove(currentDrillField);
            }
            String chartField = entry.getKey();
            DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo;
            //部门、产品分类，钻取其本身下一级或上卷上一级
            boolean downSameField = Objects.equals(currentDrillField.getDrillWay(), ChartDrillWayEnum.DOWN_SAME_FIELD.getCode());
            if (downSameField) {
                //钻取字段仍然是新的分组字段，这种特殊字段的特殊钻取无需获取其前后字段，但是要获取子部门、子分类
                drillResultChartFieldInfoPojo = new DrillResultChartFieldInfoPojo(chartField, currentDrillField, drillDir, currentDrillField, drillCondition);
                if (up) {
                    upSpecialList.add(drillResultChartFieldInfoPojo);
                } else {
                    downSpecialList.add(drillResultChartFieldInfoPojo);
                }
            } else {
                drillResultChartFieldInfoPojo = new DrillResultChartFieldInfoPojo(chartField, currentDrillField, drillDir, drillCondition);
            }
            String drillUuid = currentDrillField.getDrillUuid();
            uuidList.add(drillUuid);
            uuidFieldMap.put(drillUuid, drillResultChartFieldInfoPojo);
            chartFieldInfoMap.put(chartField, drillResultChartFieldInfoPojo);
            if (CollectionUtils.isNotEmpty(drillCondition)) {
                allCondition.addAll(drillCondition);
            }
        }
        if (noDrill) {
            return drillResultPojo;
        }
        //处理特殊字段下钻，下级部门、分类条件塞入allCondition
        dealWithDownSpecial(corpid, downSpecialList, allCondition);
        dealWithUpSpecial(corpid, upSpecialList, allCondition);
        JSONArray filter = JsonHelperUtil.parseArray(JSON.toJSONString(allCondition));
        drillResultChartInfoPojo.setFilter(filter);
        drillResultChartInfoPojo.setChartFieldInfoMap(chartFieldInfoMap);
        resultChartInfoMap.put(chartId, drillResultChartInfoPojo);
        //-------------------（2）通过前端的当前钻取字段，根据上卷、还是下钻，以及钻取层级，得到最终钻取后的目标字段
        getGoalDrillField(drillList, uuidList, uuidFieldMap, chartEntityList);
        drillResultPojo.setDrillFlag(true);
        drillResultPojo.setResultChartInfoMap(resultChartInfoMap);
        return drillResultPojo;
    }
    /**
     * 重置图表的分类、系列、行列分组字段
     * @param drillResultPojo 该图表
     * @param chartEntity
     * @return com.xbongbong.pro.statistic.result.pojo.DrillResultChartInfoPojo
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public DrillResultChartInfoPojo resetChartInfo(DrillResultPojo drillResultPojo, ChartEntity chartEntity){
        if (Objects.isNull(drillResultPojo)) {
            return null;
        }
        if (!drillResultPojo.getDrillFlag()) {
            return null;
        }
        DrillResultChartInfoPojo drillResultChartInfoPojo = drillResultPojo.getResultChartInfoMap().get(chartEntity.getId());
        if (Objects.isNull(drillResultChartInfoPojo)) {
            return null;
        }
        //新的条件塞入
        JSONArray filter = drillResultChartInfoPojo.getFilter();
        if (CollectionUtils.isNotEmpty(filter)) {
            JSONArray chartFilter = chartEntity.getFilter();
            if (Objects.isNull(chartFilter)) {
                chartFilter = new JSONArray();
            }
            for (int i = 0; i < filter.size(); i++) {
                JSONObject jsonObject = filter.getJSONObject(i);
                Integer fieldType = jsonObject.getInteger(FieldAttrConstant.FIELD_TYPE);
                // 这是前段传过来的值
                String valueText = jsonObject.getString(FieldAttrConstant.VALUE_TEXT);
                if (EsHelper.isDateTimeByFieldType(fieldType) && StringUtil.isNotEmpty(valueText)) {
                    String value = jsonObject.getString(FieldAttrConstant.VALUE);
                    // 时间戳转为时间范围,改成long是因为int最大值就到2038年
                    dealTimeRangeLong(jsonObject, value);
                }
                chartFilter.add(jsonObject);
            }
            chartEntity.setFilter(chartFilter);
        }
        Map<String, DrillResultChartFieldInfoPojo> chartFieldInfoMap = drillResultChartInfoPojo.getChartFieldInfoMap();
        if (Objects.isNull(chartFieldInfoMap)) {
            return drillResultChartInfoPojo;
        }
        //遍历改图钻取了的字段（分类或系列、行列）
        for (Map.Entry<String, DrillResultChartFieldInfoPojo> entry : chartFieldInfoMap.entrySet()) {
            //钻取字段所对应的chart属性（分类、系列、行列分组）
            String chartField = entry.getKey();
            //先读出图表的原分类、系列、行列字段
            Object object = ReflectHelper.valueGet(chartEntity, chartField);
            if (Objects.isNull(object)) {
                continue;
            }
            JSONArray jsonArray = (JSONArray) object;

            retentionRowDateField(chartField,jsonArray,chartEntity);

            //该图表该字段（分类、系列、行列分组）的钻取信息
            DrillResultChartFieldInfoPojo value = entry.getValue();
            //钻取的字段（即分组内需要替换成goalDrillField的字段attr）
            List<String> currentDrillAttrList = value.getCurrentDrillAttrList();
            if (CollectionUtils.isEmpty(currentDrillAttrList)) {
                continue;
            }
            //目标钻取字段，要替换原分组字段
            FieldAttrPojo goalDrillField = value.getGoalDrillField();
            String goalAttr = goalDrillField.getAttr();
            String dateGroupType = goalDrillField.getDateGroupType();
            boolean updateFlag = false;
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String attr = jsonObject.getString(FieldAttrConstant.ATTR);
                boolean flag = Objects.equals(attr, goalAttr);
                if (flag && !EsHelper.isDateTimeByFieldType(jsonObject.getInteger(FieldAttrConstant.FIELD_TYPE))){
                    //非时间字段且attr相等：部门、产品分类逐级下钻时，不把分组字段替换（防止后续渲染图表使用value等出错 - 重置goalDrillField的value等会比较麻烦，会同时影响filter）
                    break;
                }
                if (flag && Objects.equals(jsonObject.getString(FieldAttrConstant.DATE_GROUP_TYPE), dateGroupType)){
                    //时间字段，attr及dateGroupType都一致，也不替换（防止后续渲染图表使用value等出错 - 重置goalDrillField的value等会比较麻烦，会同时影响filter）
                    break;
                }
                //同一个层级字段不会同时存在于分类系列，行列。
                if (currentDrillAttrList.contains(attr)) {
                    //替换为钻取目标字段
                    FieldAttrPojo newGoalDrillField = new FieldAttrPojo();
                    BeanUtil.copyProperties(goalDrillField, newGoalDrillField);
                    newGoalDrillField.setValue(null);
                    newGoalDrillField.setValueText(null);
                    jsonArray.set(i, JSONObject.parse(JSON.toJSONString(newGoalDrillField)));
                    updateFlag = true;
                    break;
                }
            }
            if (updateFlag) {
                //最新的分类、系列、行列分组字段置入chart
                ReflectHelper.valueSet(chartEntity, chartField, jsonArray);
            }
        }
        return drillResultChartInfoPojo;
    }

    /**
     * 钻取时，额外存一下行字段的第一个时间字段
     *
     * @param chartField
     * @param rowFiledArray
     * @param chartEntity
     * @author zyy
     * @date 2023/3/22
     * @version v1.0
     */
    private void retentionRowDateField(String chartField, JSONArray rowFiledArray, ChartEntity chartEntity) {
        //非行分组 或 行分组无数据，则返回
        if(!"rowGroupAttr".equals(chartField) || CollectionsUtil.isEmpty(rowFiledArray)){
            return;
        }
        //取出第一个行分组原字段
        JSONObject jsonObject = rowFiledArray.getJSONObject(0);
        //保留原字段
        chartEntity.setOriginalRowField(jsonObject);
    }

    /**
     * 把前端传的时间变成一个范围操作(long类型的)
     *
     * @param jsonObject 需要改变的对象
     * @param value      需要改变的时间戳对象
     */
    public void dealTimeRangeLong(JSONObject jsonObject, String value) {
        long date;
        if (value.contains(CustomChartConstant.TIME_Z)) {
            String valueTemp = value.replace("Z", " UTC");
            date = DateTimeUtil.getLong(valueTemp, DateTimeUtil.SDF_Z);
        } else {
            date = Long.parseLong(value) / 1000;
        }
        String dateGroupType = jsonObject.getString(FieldAttrConstant.DATE_GROUP_TYPE);
        IntervalTypeEnum intervalTypeEnum = IntervalTypeEnum.getByFormatStr(dateGroupType);
        long todayBegin = DateTimeUtil.getTodayInt(date);
        long todayEnd;
        switch (intervalTypeEnum) {
            case YEAR_QUARTER:
                todayEnd = DateTimeUtil.getFirstDateOfNextSeason(date);
                break;
            case YEAR_MONTH:
                todayEnd = DateTimeUtil.getLastDateOfMonthInSomeday(date);
                break;
            case YEAR_WEEK:
                todayEnd = DateTimeUtil.getWeekLastDayInSomeday(date);
                break;
            case YEAR:
                todayEnd = DateTimeUtil.getLastDateOfYear(date);
                break;
            default:
                todayEnd = DateTimeUtil.getTodayEndInt(date);
                break;
        }
        jsonObject.put(StringConstant.SYMBOL, ConditionEnum.RANGE.getSymbol());
        List<Long> list = new ArrayList<>();
        list.add(todayBegin);
        list.add(todayEnd);
        jsonObject.put(FieldAttrConstant.VALUE, list);
    }

    /**
     * 把前端传的时间变成一个范围操作
     *
     * @param jsonObject 需要改变的对象
     * @param value      需要改变的时间戳对象
     */
    public void dealTimeRange(JSONObject jsonObject, String value) {
        int date;
        if (value.contains(CustomChartConstant.TIME_Z)) {
            String valueTemp = value.replace("Z", " UTC");
            date = DateUtil.getInt(valueTemp, DateTimeUtil.SDF_Z);
        } else {
            date = DateUtil.getInt(Long.valueOf(value));
        }
        String dateGroupType = jsonObject.getString("dateGroupType");
        IntervalTypeEnum intervalTypeEnum = IntervalTypeEnum.getByFormatStr(dateGroupType);
        int todayBegin = DateUtil.getTodayInt(date);
        int todayEnd;
        switch (intervalTypeEnum) {
            case YEAR_QUARTER:
                todayEnd = DateUtil.getQuarterEndInt(date);
                break;
            case YEAR_MONTH:
                todayEnd = DateUtil.getLastDateOfMonthInSomeday(date);
                break;
            case YEAR_WEEK:
                todayEnd = DateUtil.getWeekLastDayInSomeday(date);
                break;
            case YEAR:
                todayEnd = DateUtil.getLastDateOfYear(date);
                break;
            default:
                todayEnd = DateUtil.getTodayEndInt(date);
                break;
        }
        jsonObject.put("symbol", ConditionEnum.RANGE.getSymbol());
        List<Integer> list = new ArrayList<>();
        list.add(todayBegin);
        list.add(todayEnd);
        jsonObject.put("value", list);
    }

    /**
     * 得到目标钻取字段，封装currentDrillAttrList，并处理每个钻取字段的conditionToTableList（移除非该钻取字段所属层级的条件 - 用于后续渲染结果时在表内拼入钻取前的内容）
     * 注：获取的是非特殊字段（部门、产品分类）的钻取目标字段获取；或者特殊字段没有子级部门、子级产品分类时转为其他钻取字段
     * @param drillList 钻取配置内层级list
     * @param uuidList 前端传入当前钻取字段的uuid集合
     * @param uuidFieldMap key：当前钻取字段所属层级uuid；value：钻取方向（上卷、下钻）、钻取图表字段（分类、系列、行列）、当前钻取字段及其所属层级attrList等信息pojo
     * @param chartEntityList 钻取图表实体
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void getGoalDrillField(List<ChartDrillItemPojo> drillList, Set<String> uuidList, Map<String, DrillResultChartFieldInfoPojo> uuidFieldMap, List<ChartEntity> chartEntityList) throws XbbException {
        ChartEntity chartEntity = chartEntityList.get(0);
        for (ChartDrillItemPojo drillItemPojo : drillList) {
            String uuid = drillItemPojo.getUuid();
            //每个层级（特殊字段uuid没有塞入uuidList、uuidFieldMap，因为上面已经处理）
//            TODO 如果特殊字段无上下级，是否可以塞入继续找下一个字段
            if (!uuidList.contains(uuid)) {
                continue;
            }
            //层级内的字段
            List<FieldAttrPojo> field = drillItemPojo.getField();
            //比较层级内字段与当前钻取方向的问题
            if (CollectionUtils.isEmpty(field)) {
                continue;
            }
            //uuidList有，则uuidFieldMap肯定有。然后通过uuidFieldMap获取的当前钻取字段信息，去获取其前一个or下一个字段（特殊字段的则转为条件）
            DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo = uuidFieldMap.get(uuid);
            //把当前钻取字段所属层级内的所有attr集合置入drillResultChartFieldInfoPojo
            List<String> currentDrillAttrList = field.stream().map(df -> df.getAttr()).collect(Collectors.toList());
            drillResultChartFieldInfoPojo.setCurrentDrillAttrList(currentDrillAttrList);
            //移除conditionToTableList内非该层级字段的条件
            List<FieldAttrPojo> lastConditionList = drillResultChartFieldInfoPojo.getConditionToTableList().stream().filter(c -> currentDrillAttrList.contains(c.getAttr())).collect(Collectors.toList());
            drillResultChartFieldInfoPojo.setConditionToTableList(lastConditionList);
            //点击钻取的字段
            FieldAttrPojo currentDrillField = drillResultChartFieldInfoPojo.getCurrentDrillField();
            //部门、产品分类，钻取其本身下一级或上卷上一级
            boolean downSameField = Objects.equals(currentDrillField.getDrillWay(), ChartDrillWayEnum.DOWN_SAME_FIELD.getCode());
            if (downSameField) {
                // 特殊字段图下钻的时候需要处理一下钻取字段所在层级索引，但是不用再找下一个字段
                int drillIndex = drillHelp.getDrillIndex(currentDrillField, currentDrillAttrList, field);
                chartEntity.setDrillIndex(drillIndex);
                continue;
            }
            String drillDir = drillResultChartFieldInfoPojo.getDrillDir();
            DrillDirEnum drillDirEnum = DrillDirEnum.getByAlias(drillDir);
            if (Objects.isNull(drillDirEnum)) {
                continue;
            }
            int fieldSize = field.size();
            switch (drillDirEnum) {
                case UP:
                    //上卷的时候，点击的字段就是上卷字段：点击字段右侧的减号上卷，是把右侧的收起来，回到用点击字段分组
                    drillResultChartFieldInfoPojo.setGoalDrillField(currentDrillField);
                    //只有统计图才需要drillIndex
                    int drillIndex = drillHelp.getDrillIndex(currentDrillField, currentDrillAttrList, field);
                    chartEntity.setDrillIndex(drillIndex);
                    currentDrillField.setValue(null);
                    currentDrillField.setValueText(null);
                    break;
                case DOWN:
                    for (int i = 0; i < fieldSize; i++) {
                        //层级内各个级别的钻取字段
                        FieldAttrPojo chartFieldAttrPojo = field.get(i);
                        if (!drillHelp.drillMatchRule(chartFieldAttrPojo, currentDrillField)) {
                            continue;
                        }
                        //层级内最后一个字段，且为下钻，则无法下钻
                        if (Objects.equals(i, (fieldSize - 1))) {
                            throw new XbbException(BiErrorCodeEnum.API_ERROR_241027);
                        }
                        int goalIndex = i + 1;
                        //下一个字段为下钻后的字段
                        FieldAttrPojo goalDrillField = field.get(goalIndex);
                        chartEntity.setDrillIndex(goalIndex);
                        drillResultChartFieldInfoPojo.setGoalDrillField(goalDrillField);
                        //找到钻取目标字段，则结束
                        break;
                    }
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 下钻：处理特殊字段（部门、产品分类）为逐级下钻字段内部结构形式时的钻取字段、条件处理
     * @param corpid
     * @param downSpecialList 该图表下钻字段信息（因行列可能同时钻取，因此为list）
     * @param allCondition 钻取后该图表所有条件信息（分类或系列其一，行列其一或全部）
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void dealWithDownSpecial(String corpid, List<DrillResultChartFieldInfoPojo> downSpecialList, List<FieldAttrPojo> allCondition) throws XbbException {
        if (CollectionUtils.isEmpty(downSpecialList)) {
            return;
        }
        List<Integer> dep = FieldTypeEnum.depList();
        List<Integer> category = FieldTypeEnum.categoryList();
        for (DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo : downSpecialList) {
            //特殊字段钻取前后字段一致
            FieldAttrPojo currentDrillField = drillResultChartFieldInfoPojo.getCurrentDrillField();
            Object value = currentDrillField.getValue();
            if (Objects.isNull(value)) {
                continue;
            }
            Long id = Long.parseLong(value.toString());
            Integer fieldType = currentDrillField.getFieldType();
            if (dep.contains(fieldType)) {
                //包含部门本身
                /*
                  下钻的直接获取部门的下级部门，循环内单个部门获取其下级部门：
                  1、downSpecialList 大小最多两个（行列都是部门类型字段且刚好钻取时才会查询），且从缓存内查询
                  2、某个部门无下级部门时要提示
                 */
                List<DepartmentEntity> subDepList = departmentModel.getSubOneLevelFromJedis(corpid, id, false);
                if (packageLastCondition(CollectionUtils.isEmpty(subDepList), allCondition, currentDrillField, id)) {
                    //subDepList为空时，把最后一个部门id作为条件塞入，并置为找下一层级字段
                    return;
                }
                List<IdNamePojo> depCondition = new ArrayList<>();
                for (DepartmentEntity entity : subDepList) {
                    depCondition.add(new IdNamePojo(entity.getId(), entity.getName()));
                }
                //其他所有子部门作为条件塞入
                packageSubCondition(allCondition, currentDrillField, depCondition);
            } else if (category.contains(fieldType)) {
                //包含父分类本身
                List<ProductCategoryEntity> subCategoryList = productCategoryModel.getSubOneLevelFromJedis(corpid, id, false);
                if (packageLastCondition(CollectionUtils.isEmpty(subCategoryList), allCondition, currentDrillField, id)) {
                    //subDepList为空时，把最后一个产品分类id作为条件塞入，并置为找下一层级字段
                    return;
                }
                List<IdNamePojo> categoryCondition = new ArrayList<>();
                for (ProductCategoryEntity entity : subCategoryList) {
                    categoryCondition.add(new IdNamePojo(entity.getId(), entity.getName()));
                }
                packageSubCondition(allCondition, currentDrillField, categoryCondition);
            }
            //钻取特殊字段条件已经转换为子部门、子分类，其本身的条件移除
            allCondition.remove(currentDrillField);
        }
    }

    /**
     * 上卷：处理特殊字段（部门、产品分类）为逐级下钻字段内部结构形式时的钻取字段、条件处理
     * @param corpid
     * @param upSpecialList 该图表上卷字段信息（因行列可能同时钻取，因此为list）
     * @param allCondition 钻取后该图表所有条件信息（分类或系列其一，行列其一或全部）
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void dealWithUpSpecial(String corpid, List<DrillResultChartFieldInfoPojo> upSpecialList, List<FieldAttrPojo> allCondition) throws XbbException {
        if (CollectionUtils.isEmpty(upSpecialList)) {
            return;
        }
        List<Integer> dep = FieldTypeEnum.depList();
        List<Integer> category = FieldTypeEnum.categoryList();
        Set<Long> depIdSet = Sets.newHashSetWithExpectedSize(upSpecialList.size());
        Set<Long> categoryIdSet = Sets.newHashSetWithExpectedSize(upSpecialList.size());
        for (DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo : upSpecialList) {
            //特殊字段钻取前后字段一致
            FieldAttrPojo currentDrillField = drillResultChartFieldInfoPojo.getCurrentDrillField();
            Object value = currentDrillField.getValue();
            if (Objects.isNull(value)) {
                continue;
            }
            Long id = Long.parseLong(value.toString());
            currentDrillField.setValueLong(id);
            Integer fieldType = currentDrillField.getFieldType();
            if (dep.contains(fieldType)) {
                depIdSet.add(id);
            } else if (category.contains(fieldType)) {
                categoryIdSet.add(id);
            }
        }
        if (CollectionUtils.isNotEmpty(depIdSet)) {
            //key：部门id（点减号的部门id）；value：与该部门同级的部门id集合（且包含其父部门，如果其parentId=0，则为本身）
            Map<Long, List<DepartmentEntity>> sameLevelMap = Maps.newHashMapWithExpectedSize(depIdSet.size());
            List<DepartmentEntity> depList = departmentModel.getByDepIdIn(corpid, depIdSet);
            for (DepartmentEntity departmentEntity : depList) {
                //点击减号的部门id
                Long id = departmentEntity.getId();
                //该部门的上级部门id（点减号后，要聚合的是该部门上级部门的所有下一级部门）
                Long parentId = departmentEntity.getParentId();
                if (Objects.equals(parentId, BasicConstant.ZERO_LONG)) {
                    sameLevelMap.put(id, Arrays.asList(departmentEntity));
                } else {
                    //该部门上级部门的所有下一级部门，且不包含其父部门
                    List<DepartmentEntity> subDepList = departmentModel.getSubOneLevelFromJedis(corpid, parentId, false);
                    sameLevelMap.put(id, subDepList);
                }
            }
            for (DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo : upSpecialList) {
                //特殊字段钻取前后字段一致
                FieldAttrPojo currentDrillField = drillResultChartFieldInfoPojo.getGoalDrillField();
                Long id = currentDrillField.getValueLong();
                if (Objects.isNull(id)) {
                    continue;
                }
                List<DepartmentEntity> parentSubDepList = sameLevelMap.get(id);
                if (CollectionUtils.isEmpty(parentSubDepList)) {
                    //原则上，点击某个部门上卷时，是会获取其上级部门的所有下一级部门，也就是至少会包含点击的部门，不会为空
                    continue;
                }
                //parentSubDepList不为空，则depCondition肯定也不为空
                List<IdNamePojo> depCondition = new ArrayList<>();
                for (DepartmentEntity entity : parentSubDepList) {
                    depCondition.add(new IdNamePojo(entity.getId(), entity.getName()));
                }
                //其他所有子部门作为条件塞入
                packageSubCondition(allCondition, currentDrillField, depCondition);
            }
        }
        if (CollectionUtils.isNotEmpty(categoryIdSet)) {
            //key：产品分类id（点减号的产品分类id）；value：与该产品分类同级的产品分类id集合（且包含其父产品分类，如果其parentId=0，则为本身）
            Map<Long, List<ProductCategoryEntity>> sameLevelMap = Maps.newHashMapWithExpectedSize(depIdSet.size());
            List<ProductCategoryEntity> productCategoryList = productCategoryModel.getProductCategoryListByIdIn(corpid, categoryIdSet);
            for (ProductCategoryEntity productCategoryEntity : productCategoryList) {
                //点击减号的分类id
                Long id = productCategoryEntity.getId();
                //该产品分类的上级产品分类id（点减号后，要聚合的是该产品分类上级产品分类的所有下一级产品分类）
                Long parentId = productCategoryEntity.getParentId();
                if (Objects.equals(parentId, BasicConstant.ZERO_LONG)) {
                    sameLevelMap.put(id, Arrays.asList(productCategoryEntity));
                } else {
                    //该产品分类上级产品分类的所有下一级产品分类，且不包含其父产品分类
                    List<ProductCategoryEntity> subDepList = productCategoryModel.getSubOneLevelFromJedis(corpid, parentId, false);
                    sameLevelMap.put(id, subDepList);
                }
            }
            for (DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo : upSpecialList) {
                //特殊字段钻取前后字段一致
                FieldAttrPojo currentDrillField = drillResultChartFieldInfoPojo.getGoalDrillField();
                Long id = currentDrillField.getValueLong();
                if (Objects.isNull(id)) {
                    continue;
                }
                List<ProductCategoryEntity> parentSubDepList = sameLevelMap.get(id);
                if (CollectionUtils.isEmpty(parentSubDepList)) {
                    //原则上，点击某个产品分类上卷时，是会获取其上级产品分类的所有下一级产品分类，也就是至少会包含点击的产品分类，不会为空
                    continue;
                }
                //parentSubDepList不为空，则depCondition肯定也不为空
                List<IdNamePojo> categoryCondition = new ArrayList<>();
                for (ProductCategoryEntity entity : parentSubDepList) {
                    categoryCondition.add(new IdNamePojo(entity.getId(), entity.getName()));
                }
                //其他所有子产品分类作为条件塞入
                packageSubCondition(allCondition, currentDrillField, categoryCondition);
            }
        }
    }

    /**
     * 子部门/子产品分类为空时，把最后一个部门id作为条件塞入，并置为找下一层级字段
     * @param empty 子部门/子产品分类是否为空
     * @param allCondition 钻取后该图表所有条件信息（分类或系列其一，行列其一或全部）
     * @param currentDrillField 钻取字段
     * @param id 部门、分类id
     * @return boolean
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private boolean packageLastCondition(boolean empty, List<FieldAttrPojo> allCondition, FieldAttrPojo currentDrillField, Long id) {
        if (empty) {
            //当该部门无下一级时，切为下一个字段，而非提示无下级部门
            //throw new XbbException(BiErrorCodeEnum.API_ERROR_241028, BiErrorCodeEnum.API_ERROR_241028.getMsg(), currentDrillField.getValueText());
            currentDrillField.setDrillWay(ChartDrillWayEnum.DOWN_NEXT.getCode());
            // 最后一个部门作为条件塞入
            FieldAttrPojo condition = new FieldAttrPojo();
            BeanUtil.copyProperties(currentDrillField, condition);
            condition.setSymbol(ConditionEnum.IN.getSymbol());
            condition.setValue(id);
            allCondition.add(condition);
            return true;
        }
        return false;
    }

    /**
     * 把子部门/子产品分类集合塞入condition作为条件，即钻取下一层级后只聚合这些子部门/子产品分类
     * @param allCondition 钻取后该图表所有条件信息（分类或系列其一，行列其一或全部）
     * @param currentDrillField 钻取字段
     * @param subCondition 子部门/子产品分类条件集合
     * @return void
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void packageSubCondition(List<FieldAttrPojo> allCondition, FieldAttrPojo currentDrillField, List<IdNamePojo> subCondition) {
        //其他所有子部门/子产品分类作为条件塞入
        FieldAttrPojo condition = new FieldAttrPojo();
        BeanUtil.copyProperties(currentDrillField, condition);
        condition.setSymbol(ConditionEnum.IN.getSymbol());
        condition.setValue(subCondition);
        //新的子分类条件塞入该图表整体全部condition
        allCondition.add(condition);
    }
}
